<!DOCTYPE html>
<html lang="zh-CN">
<head>
  <meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=2">
<meta name="theme-color" content="#222">
<meta name="generator" content="Hexo 5.4.0">
  <link rel="apple-touch-icon" sizes="180x180" href="/images/M.png">
  <link rel="icon" type="image/png" sizes="32x32" href="/images/M.png">
  <link rel="icon" type="image/png" sizes="16x16" href="/images/M.png">

<link rel="stylesheet" href="/css/main.css">


<link rel="stylesheet" href="/lib/font-awesome/css/all.min.css">
  <link rel="stylesheet" href="/lib/pace/pace-theme-minimal.min.css">
  <script src="/lib/pace/pace.min.js"></script>

<script id="hexo-configurations">
    var NexT = window.NexT || {};
    var CONFIG = {"hostname":"maureen-liu.gitee.io","root":"/","scheme":"Gemini","version":"7.8.0","exturl":false,"sidebar":{"position":"left","display":"post","padding":18,"offset":12,"onmobile":false},"copycode":{"enable":true,"show_result":true,"style":null},"back2top":{"enable":true,"sidebar":true,"scrollpercent":true},"bookmark":{"enable":false,"color":"#222","save":"auto"},"fancybox":false,"mediumzoom":false,"lazyload":false,"pangu":false,"comments":{"style":"tabs","active":"valine","storage":true,"lazyload":false,"nav":null,"activeClass":"valine"},"algolia":{"hits":{"per_page":10},"labels":{"input_placeholder":"Search for Posts","hits_empty":"We didn't find any results for the search: ${query}","hits_stats":"${hits} results found in ${time} ms"}},"localsearch":{"enable":true,"trigger":"auto","top_n_per_article":1,"unescape":false,"preload":false},"motion":{"enable":true,"async":false,"transition":{"post_block":"fadeIn","post_header":"slideDownIn","post_body":"slideDownIn","coll_header":"slideLeftIn","sidebar":"slideUpIn"}},"path":"search.xml"};
  </script>

  <meta name="description" content="一、编译内存相关  1、C++ 程序编译过程 面试高频指数：四星  编译过程分为四个过程：编译（编译预处理、编译、优化），汇编，链接。  编译预处理：处理以 # 开头的指令； 编译、优化：将源码 .cpp 文件翻译成 .s 汇编代码； 汇编：将汇编代码 .s 翻译成机器指令 .o文件； 链接：汇编程序生成的目标文件，即.o文件，并不会立即执行，因为可能会出现：.cpp文件中的函数引用了另一个.c">
<meta property="og:type" content="article">
<meta property="og:title" content="C++面试突击">
<meta property="og:url" content="https://maureen-liu.gitee.io/p/1cb47e9e.html">
<meta property="og:site_name" content="Maureen&#39;s blog">
<meta property="og:description" content="一、编译内存相关  1、C++ 程序编译过程 面试高频指数：四星  编译过程分为四个过程：编译（编译预处理、编译、优化），汇编，链接。  编译预处理：处理以 # 开头的指令； 编译、优化：将源码 .cpp 文件翻译成 .s 汇编代码； 汇编：将汇编代码 .s 翻译成机器指令 .o文件； 链接：汇编程序生成的目标文件，即.o文件，并不会立即执行，因为可能会出现：.cpp文件中的函数引用了另一个.c">
<meta property="og:locale" content="zh_CN">
<meta property="og:image" content="https://gitee.com/maureen-liu/typora-image/raw/master/typora-image/1612676946-HVvkdR-image.png">
<meta property="og:image" content="https://gitee.com/maureen-liu/typora-image/raw/master/typora-image/1612687346-kyLXKn-image.png">
<meta property="og:image" content="https://gitee.com/maureen-liu/typora-image/raw/master/typora-image/1612675767-guREBN-image.png">
<meta property="og:image" content="https://gitee.com/maureen-liu/typora-image/raw/master/typora-image/1618818155-PZxTzJ-image.png">
<meta property="og:image" content="https://pic.leetcode-cn.com/1627822193-yqLShF-image.png">
<meta property="og:image" content="https://pic.leetcode-cn.com/1612681846-tyqCUP-image.png">
<meta property="og:image" content="https://pic.leetcode-cn.com/1612679161-OtbPhj-image.png">
<meta property="og:image" content="https://pic.leetcode-cn.com/1612681900-RShiIP-image.png">
<meta property="og:image" content="https://pic.leetcode-cn.com/1612681846-tyqCUP-image.png">
<meta property="og:image" content="https://pic.leetcode-cn.com/1612679161-OtbPhj-image.png">
<meta property="og:image" content="https://pic.leetcode-cn.com/1612681900-RShiIP-image.png">
<meta property="og:image" content="https://pic.leetcode-cn.com/1612682073-uNdCTl-image.png">
<meta property="og:image" content="https://pic.leetcode-cn.com/1612679879-DBSJce-image.png">
<meta property="og:image" content="https://pic.leetcode-cn.com/1612682139-oQZazN-image.png">
<meta property="og:image" content="https://pic.leetcode-cn.com/1612681289-WjDonI-image.png">
<meta property="og:image" content="https://pic.leetcode-cn.com/1612682194-qhLdri-image.png">
<meta property="og:image" content="https://pic.leetcode-cn.com/1612681677-Jgekej-image.png">
<meta property="og:image" content="https://pic.leetcode-cn.com/1612681729-IhAKvb-image.png">
<meta property="article:published_time" content="2022-01-16T05:50:06.000Z">
<meta property="article:modified_time" content="2022-01-16T06:49:43.372Z">
<meta property="article:author" content="Maureen">
<meta name="twitter:card" content="summary">
<meta name="twitter:image" content="https://gitee.com/maureen-liu/typora-image/raw/master/typora-image/1612676946-HVvkdR-image.png">

<link rel="canonical" href="https://maureen-liu.gitee.io/p/1cb47e9e.html">


<script id="page-configurations">
  // https://hexo.io/docs/variables.html
  CONFIG.page = {
    sidebar: "",
    isHome : false,
    isPost : true,
    lang   : 'zh-CN'
  };
</script>
<script src="/lib/fireworks.js"></script>
  <title>C++面试突击 | Maureen's blog</title>
  






  <noscript>
  <style>
  .use-motion .brand,
  .use-motion .menu-item,
  .sidebar-inner,
  .use-motion .post-block,
  .use-motion .pagination,
  .use-motion .comments,
  .use-motion .post-header,
  .use-motion .post-body,
  .use-motion .collection-header { opacity: initial; }

  .use-motion .site-title,
  .use-motion .site-subtitle {
    opacity: initial;
    top: initial;
  }

  .use-motion .logo-line-before i { left: initial; }
  .use-motion .logo-line-after i { right: initial; }
  </style>
</noscript>

</head>

<body itemscope itemtype="http://schema.org/WebPage">
  <div class="container use-motion">
    <div class="headband"></div>

    <header class="header" itemscope itemtype="http://schema.org/WPHeader">
      <div class="header-inner"><div class="site-brand-container">
  <div class="site-nav-toggle">
    <div class="toggle" aria-label="切换导航栏">
      <span class="toggle-line toggle-line-first"></span>
      <span class="toggle-line toggle-line-middle"></span>
      <span class="toggle-line toggle-line-last"></span>
    </div>
  </div>

  <div class="site-meta">

    <a href="/" class="brand" rel="start">
      <span class="logo-line-before"><i></i></span>
      <h1 class="site-title">Maureen's blog</h1>
      <span class="logo-line-after"><i></i></span>
    </a>
      <p class="site-subtitle" itemprop="description">记录学习的点点滴滴</p>
  </div>

  <div class="site-nav-right">
    <div class="toggle popup-trigger">
        <i class="fa fa-search fa-fw fa-lg"></i>
    </div>
  </div>
</div>




<nav class="site-nav">
  <ul id="menu" class="main-menu menu">
        <li class="menu-item menu-item-home">

    <a href="/" rel="section"><i class="fa fa-home fa-fw"></i>首页</a>

  </li>
        <li class="menu-item menu-item-tags">

    <a href="/tags/" rel="section"><i class="fa fa-tags fa-fw"></i>标签</a>

  </li>
        <li class="menu-item menu-item-categories">

    <a href="/categories/" rel="section"><i class="fa fa-th fa-fw"></i>分类</a>

  </li>
        <li class="menu-item menu-item-archives">

    <a href="/archives/" rel="section"><i class="fa fa-archive fa-fw"></i>归档</a>

  </li>
      <li class="menu-item menu-item-search">
        <a role="button" class="popup-trigger"><i class="fa fa-search fa-fw"></i>搜索
        </a>
      </li>
  </ul>
</nav>



  <div class="search-pop-overlay">
    <div class="popup search-popup">
        <div class="search-header">
  <span class="search-icon">
    <i class="fa fa-search"></i>
  </span>
  <div class="search-input-container">
    <input autocomplete="off" autocapitalize="off"
           placeholder="搜索..." spellcheck="false"
           type="search" class="search-input">
  </div>
  <span class="popup-btn-close">
    <i class="fa fa-times-circle"></i>
  </span>
</div>
<div id="search-result">
  <div id="no-result">
    <i class="fa fa-spinner fa-pulse fa-5x fa-fw"></i>
  </div>
</div>

    </div>
  </div>

</div>
    </header>

    


    <main class="main">
      <div class="main-inner">
        <div class="content-wrap">
          

          <div class="content post posts-expand">
            

    
  
  
  <article itemscope itemtype="http://schema.org/Article" class="post-block" lang="zh-CN">
    <link itemprop="mainEntityOfPage" href="https://maureen-liu.gitee.io/p/1cb47e9e.html">

    <span hidden itemprop="author" itemscope itemtype="http://schema.org/Person">
      <meta itemprop="image" content="/images/stan.jpeg">
      <meta itemprop="name" content="Maureen">
      <meta itemprop="description" content="心之所向，素履以往">
    </span>

    <span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization">
      <meta itemprop="name" content="Maureen's blog">
    </span>
      <header class="post-header">
        <h1 class="post-title" itemprop="name headline">
          C++面试突击
        </h1>

        <div class="post-meta">
            <span class="post-meta-item">
              <span class="post-meta-item-icon">
                <i class="far fa-calendar"></i>
              </span>
              <span class="post-meta-item-text">发表于</span>
              

              <time title="创建时间：2022-01-16 13:50:06 / 修改时间：14:49:43" itemprop="dateCreated datePublished" datetime="2022-01-16T13:50:06+08:00">2022-01-16</time>
            </span>
            <span class="post-meta-item">
              <span class="post-meta-item-icon">
                <i class="far fa-folder"></i>
              </span>
              <span class="post-meta-item-text">分类于</span>
                <span itemprop="about" itemscope itemtype="http://schema.org/Thing">
                  <a href="/categories/C/" itemprop="url" rel="index"><span itemprop="name">C++</span></a>
                </span>
                  ，
                <span itemprop="about" itemscope itemtype="http://schema.org/Thing">
                  <a href="/categories/C/leetcode/" itemprop="url" rel="index"><span itemprop="name">leetcode</span></a>
                </span>
            </span>

          
            <span class="post-meta-item" title="阅读次数" id="busuanzi_container_page_pv" style="display: none;">
              <span class="post-meta-item-icon">
                <i class="fa fa-eye"></i>
              </span>
              <span class="post-meta-item-text">阅读次数：</span>
              <span id="busuanzi_value_page_pv"></span>
            </span>
  
  <span class="post-meta-item">
    
      <span class="post-meta-item-icon">
        <i class="far fa-comment"></i>
      </span>
      <span class="post-meta-item-text">Valine：</span>
    
    <a title="valine" href="/p/1cb47e9e.html#valine-comments" itemprop="discussionUrl">
      <span class="post-comments-count valine-comment-count" data-xid="/p/1cb47e9e.html" itemprop="commentCount"></span>
    </a>
  </span>
  
  <br>
            <span class="post-meta-item" title="本文字数">
              <span class="post-meta-item-icon">
                <i class="far fa-file-word"></i>
              </span>
                <span class="post-meta-item-text">本文字数：</span>
              <span>91k</span>
            </span>
            <span class="post-meta-item" title="阅读时长">
              <span class="post-meta-item-icon">
                <i class="far fa-clock"></i>
              </span>
                <span class="post-meta-item-text">阅读时长 &asymp;</span>
              <span>1:23</span>
            </span>

        </div>
      </header>

    
    
    
    <div class="post-body" itemprop="articleBody">
      
      
        <h1 id="一-编译内存相关"><a class="markdownIt-Anchor" href="#一-编译内存相关"></a> 一、编译内存相关</h1>
<h2 id="1-c-程序编译过程"><a class="markdownIt-Anchor" href="#1-c-程序编译过程"></a> 1、C++ 程序编译过程</h2>
<p>面试高频指数：四星</p>
<hr>
<p>编译过程分为四个过程：编译（编译预处理、编译、优化），汇编，链接。</p>
<ul>
<li><strong>编译预处理</strong>：处理以 <code>#</code> 开头的指令；</li>
<li><strong>编译、优化</strong>：将源码 <code>.cpp</code> 文件翻译成 <code>.s</code> 汇编代码；</li>
<li><strong>汇编</strong>：将汇编代码 <code>.s</code> 翻译成机器指令 <code>.o</code>文件；</li>
<li><strong>链接</strong>：汇编程序生成的目标文件，即<code>.o</code>文件，并不会立即执行，因为可能会出现：<code>.cpp</code>文件中的函数引用了另一个<code>.cpp</code>文件中定义的符号或者调用了某个库文件中的函数。那链接的目的就是将这些文件对应的目标文件链接成一个整体，从而生成可执行的程序<code>.exe</code>文件。</li>
</ul>
<p><img src="https://gitee.com/maureen-liu/typora-image/raw/master/typora-image/1612676946-HVvkdR-image.png" alt="image.png"></p>
<p>链接分为两种：</p>
<ul>
<li><strong>静态链接</strong>：代码从其所在的静态链接库中拷贝到最终的可执行程序中，在该程序被执行时，这些代码会被装入到该进程的虚拟地址空间中。</li>
<li><strong>动态链接</strong>：代码被放到动态链接库或共享对象的某个目标文件中，链接程序只是在最终的可执行程序中记录了共享对象的名字等一些信息。在程序执行时，动态链接库的全部内容会被映射到运行时相应进行的虚拟地址的空间。</li>
</ul>
<p>二者的优缺点：</p>
<ul>
<li>静态链接：<strong>浪费空间</strong>，每个可执行程序都会有目标文件的一个副本，这样如果目标文件进行了更新操作，就需要重新进行编译链接生成可执行程序（<strong>更新困难</strong>）；优点就是执行的时候运行速度快，因为可执行程序具备了程序运行的所有内容。</li>
<li>动态链接：节省内存、更新方便，但是动态链接是在程序运行时，每次执行都需要链接，相比静态链接会有一定的性能损失。</li>
</ul>
<span id="more"></span>
<h2 id="2-c内存管理"><a class="markdownIt-Anchor" href="#2-c内存管理"></a> 2、C++内存管理</h2>
<p>面试高频指数：五星</p>
<hr>
<p>C++内存分区：栈、堆、全局/静态存储区、常量存储区、代码区。</p>
<ul>
<li><strong>栈</strong>：存放函数的局部变量、函数参数、返回地址等，由编译器自动分配和释放。</li>
<li><strong>堆</strong>：动态申请的内存空间，就是由<code>malloc</code>分配的内存块，由程序员控制它的分配和释放，如果程序执行结束还没有释放，操作系统会自动回收。</li>
<li><strong>全局区/静态存储区</strong>（<code>.bss</code>段和<code>.data</code>段）：存放全局变量和静态变量，程序运行结束操作系统系统自动释放，在C语言中，未初始化的放在<code>.bss</code>段中，初始化的放在<code>.data</code>段中，C++中不再区分了。</li>
<li><strong>常量存储区</strong>（<code>.data</code>段）：存放的是常量，不允许修改，程序运行结束自动释放。</li>
<li><strong>代码区</strong>（<code>.text</code>段）：存放代码，不允许修改，但可以执行。编译后的二进制文件存放在这里。</li>
</ul>
<p>说明：</p>
<ul>
<li>从操作系统的本身来讲，以上存储区在内存中的分布式如下形式（从低地址到高地址）：<code>.text</code>段 -&gt; <code>.data</code>段 -&gt; <code>.bss</code>段 -&gt; 堆 -&gt; <code>unused</code> -&gt; 栈 -&gt; <code>env</code></li>
</ul>
<p>程序实例：</p>
<figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;iostream&gt;</span></span></span><br><span class="line"><span class="keyword">using</span> <span class="keyword">namespace</span> std;</span><br><span class="line"></span><br><span class="line"><span class="comment">/*</span></span><br><span class="line"><span class="comment">说明：C++ 中不再区分初始化和未初始化的全局变量、静态变量的存储区，如果非要区分下述程序标注在了括号中</span></span><br><span class="line"><span class="comment">*/</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">int</span> g_var = <span class="number">0</span>; <span class="comment">// g_var 在全局区（.data 段）</span></span><br><span class="line"><span class="keyword">char</span> *gp_var;  <span class="comment">// gp_var 在全局区（.bss 段）</span></span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">int</span> <span class="title">main</span><span class="params">()</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">    <span class="keyword">int</span> var;                    <span class="comment">// var 在栈区</span></span><br><span class="line">    <span class="keyword">char</span> *p_var;                <span class="comment">// p_var 在栈区</span></span><br><span class="line">    <span class="keyword">char</span> arr[] = <span class="string">&quot;abc&quot;</span>;         <span class="comment">// arr 为数组变量，存储在栈区；&quot;abc&quot;为字符串常量，存储在常量区</span></span><br><span class="line">    <span class="keyword">char</span> *p_var1 = <span class="string">&quot;123456&quot;</span>;    <span class="comment">// p_var1 在栈区；&quot;123456&quot;为字符串常量，存储在常量区</span></span><br><span class="line">    <span class="keyword">static</span> <span class="keyword">int</span> s_var = <span class="number">0</span>;       <span class="comment">// s_var 为静态变量，存在静态存储区（.data 段）</span></span><br><span class="line">    p_var = (<span class="keyword">char</span> *)<span class="built_in">malloc</span>(<span class="number">10</span>); <span class="comment">// 分配得来的 10 个字节的区域在堆区</span></span><br><span class="line">    <span class="built_in">free</span>(p_var);</span><br><span class="line">    <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<h2 id="3-栈和堆的区别"><a class="markdownIt-Anchor" href="#3-栈和堆的区别"></a> 3、栈和堆的区别</h2>
<p>面试高频指数：五星</p>
<hr>
<ul>
<li>申请方式：栈是系统自动分配，堆是程序员主动申请。</li>
<li>申请后系统响应：分配栈空间，如果剩余空间大于申请空间则分配成功，否则分配失败栈溢出；申请堆空间，堆在内存中呈现的方式类似于链表（记录空闲地址空间的链表），在链表上寻找第一个大于申请空间的节点分配给程序，将该节点从链表中删除，大多数系统中该块空间的首地址存放的是本次分配空间的大小，便于释放，将该块空间上的剩余空间再次连接在空闲链表上。</li>
<li>栈在内存中是连续的一块空间（向低地址扩展）最大容量是系统预定好的，堆在内存中的空间（向高地址扩展）是不连续的。</li>
<li>申请效率：栈是由系统自动分配，申请效率高，但程序员无法控制；堆是由程序员主动申请，效率低，使用起来方便但是容易产生碎片。</li>
<li>存放的内容：栈中存放的是局部变量，函数的参数；堆中存放的内容由程序员控制。</li>
</ul>
<h2 id="4-变量的区别"><a class="markdownIt-Anchor" href="#4-变量的区别"></a> 4、变量的区别</h2>
<p>面试高频指数：三星</p>
<hr>
<p><strong>全局变量、局部变量、静态全局变量、静态局部变量的区别</strong></p>
<p>C++变量根据定义的位置的不同的生命周期，具有不同的作用域，作用域可分为 6 种：全局作用域，局部作用域，语句作用域，类作用域，命名空间作用域和文件作用域。</p>
<p>从作用域看：</p>
<ul>
<li><strong>全局变量</strong>：具有全局作用域。全局变量只需在一个源文件中定义，就可以作用于所有的源文件。当然，其他不包含全局变量定义的源文件需要用<code>extern</code>关键字再次声明这个全局变量。</li>
<li><strong>静态全局变量</strong>：具有文件作用域。它与全局变量的区别在于如果程序包含多个文件的话，它作用于定义它的文件里，不能作用到其它文件里，即被 <code>static</code> 关键字修饰过的变量具有文件作用域。这样即使两个不同的源文件都定义了相同名字的静态全局变量，它们也是不同的变量。</li>
<li><strong>局部变量</strong>：具有局部作用域。它是自动对象（<code>auto</code>)，在程序运行期间不是一直存在，而是只在函数执行期间存在，函数的一次调用执行结束后，变量被撤销，其所占用的内存也被收回。</li>
<li><strong>静态局部变量</strong>：具有局部作用域。它只被初始化一次，自从第一次被初始化直到程序运行结束都一直存在，它和全局变量的区别在于全局变量对所有的函数都是可见的，而静态局部变量只对定义自己的函数体始终可见。</li>
</ul>
<p>从分配内存空间看：</p>
<ul>
<li>静态存储区：全局变量，静态局部变量，静态全局变量。</li>
<li>栈：局部变量。</li>
</ul>
<p>说明：</p>
<ul>
<li>静态变量和栈变量（存储在栈中的变量）、堆变量（存储在堆中的变量）的区别：静态变量会被放在程序的静态数据存储区（<code>.data</code>段）中（静态变量会自动初始化），这样可以在下一次调用的时候还可以保持原来的赋值。而栈变量或堆变量不能保证在下一次调用的时候依然保持原来的值。</li>
<li>静态变量和全局变量的区别：静态变量用<code>static</code>告知编译器，自己仅仅在变量的作用范围内可见。</li>
</ul>
<h2 id="5-全局变量定义在头文件中有什么问题"><a class="markdownIt-Anchor" href="#5-全局变量定义在头文件中有什么问题"></a> 5、全局变量定义在头文件中有什么问题？</h2>
<p>面试高频指数：1星</p>
<hr>
<p>如果在头文件中定义全局变量，当该头文件被多个文件 <code>include</code> 时，该头文件中的全局变量就会被定义多次，导致重复定义，因此不能在头文件中定义全局变量。</p>
<h2 id="6-对象创建限制在堆或栈"><a class="markdownIt-Anchor" href="#6-对象创建限制在堆或栈"></a> 6、对象创建限制在堆或栈</h2>
<p>面试高频指数：三星</p>
<hr>
<p><strong>如何限制类的对象只能在堆上创建？如何限制对象只能在栈上创建？</strong></p>
<p>说明：C++ 中的类的对象的建立分为两种：静态建立、动态建立。</p>
<ul>
<li>静态建立：由编译器为对象在栈空间上分配内存，直接调用类的构造函数创建对象。例如：<code>A a;</code></li>
<li>动态建立：使用 <code>new</code> 关键字在堆空间上创建对象，底层首先调用 <code>operator new()</code> 函数，在堆空间上寻找合适的内存并分配；然后，调用类的构造函数构造对象。例如：<code>A *p = new A();</code></li>
</ul>
<p>限制对象只能建立在堆上：</p>
<ul>
<li>
<p>最直观的思想：避免直接调用类的构造函数，因为对象静态建立时，会调用类的构造函数创建对象。但是直接将类的构造函数设为私有并不可行，因为当构造函数设为私有后，不能在类的外部调用构造函数来构造对象，只能用 <code>new</code> 来建立对象。但是由于 <code>new</code> 创建对象时，底层也会调用类的构造函数，将构造函数设为私有后，那就无法在类的外部使用 <code>new</code> 创建对象了。因此，这种方法不可行。</p>
</li>
<li>
<p>解决方法 1：</p>
<ul>
<li>
<p>将析构函数设置为私有。原因：静态对象建立在栈上，是由编译器分配和释放内存空间，编译器为对象分配内存空间时，会对类的非静态函数进行检查，即编译器会检查析构函数的访问性。当析构函数设为私有时，编译器创建的对象就无法通过访问析构函数来释放对象的内存空间，因此，编译器不会在栈上为对象分配内存。</p>
  <figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">A</span></span></span><br><span class="line"><span class="class">&#123;</span></span><br><span class="line"><span class="keyword">public</span>:</span><br><span class="line">    <span class="built_in">A</span>() &#123;&#125;</span><br><span class="line">    <span class="function"><span class="keyword">void</span> <span class="title">destory</span><span class="params">()</span></span></span><br><span class="line"><span class="function">    </span>&#123;</span><br><span class="line">        <span class="keyword">delete</span> <span class="keyword">this</span>;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">private</span>:</span><br><span class="line">    ~<span class="built_in">A</span>()</span><br><span class="line">    &#123;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;;</span><br></pre></td></tr></table></figure>
<p>该方法存在的问题：</p>
</li>
<li>
<p>用 <code>new</code> 创建的对象，通常会使用 <code>delete</code> 释放该对象的内存空间，但此时类的外部无法调用析构函数，因此类内必须定义一个 <code>destroy()</code> 函数，用来释放 <code>new</code> 创建的对象。</p>
</li>
<li>
<p>无法解决多继承问题，因为如果这个类作为基类，析构函数要设置成 <code>virtual</code>，然后在派生类中重写该函数，来实现多态。但此时，析构函数是私有的，派生类中无法访问。</p>
</li>
</ul>
</li>
<li>
<p>解决方法 2：</p>
<ul>
<li>
<p>构造函数设置为 <code>protected</code>，并提供一个 <code>public</code> 的静态函数来完成构造，而不是在类的外部使用 <code>new</code> 构造；将析构函数设置为<code>protected</code>。原因：类似于单例模式，也保证了在派生类中能够访问析构函数。通过调用 <code>create()</code> 函数在堆上创建对象。</p>
  <figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br></pre></td><td class="code"><pre><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">A</span></span></span><br><span class="line"><span class="class">&#123;</span></span><br><span class="line"><span class="keyword">protected</span>:</span><br><span class="line">    <span class="built_in">A</span>() &#123;&#125;</span><br><span class="line">    ~<span class="built_in">A</span>() &#123;&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">public</span>:</span><br><span class="line">    <span class="function"><span class="keyword">static</span> A *<span class="title">create</span><span class="params">()</span></span></span><br><span class="line"><span class="function">    </span>&#123;</span><br><span class="line">        <span class="keyword">return</span> <span class="keyword">new</span> <span class="built_in">A</span>();</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="function"><span class="keyword">void</span> <span class="title">destory</span><span class="params">()</span></span></span><br><span class="line"><span class="function">    </span>&#123;</span><br><span class="line">        <span class="keyword">delete</span> <span class="keyword">this</span>;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;;</span><br></pre></td></tr></table></figure>
</li>
</ul>
</li>
</ul>
<p>限制对象只能建立在栈上：</p>
<ul>
<li>
<p>解决方法：将 <code>opeartor new()</code> 设置为私有。原因：当对象建立在堆上时，是采用 <code>new</code> 的方式进行建立，其底层会调用<code>operator new()</code> 函数，因此只要对该函数加以限制，就能够防止对象建立在堆上。</p>
  <figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">A</span></span></span><br><span class="line"><span class="class">&#123;</span></span><br><span class="line"><span class="keyword">private</span>:</span><br><span class="line">    <span class="function"><span class="keyword">void</span> *<span class="keyword">operator</span> <span class="title">new</span><span class="params">(<span class="keyword">size_t</span> t)</span> </span>&#123;&#125;    <span class="comment">// 注意函数的第一个参数和返回值都是固定的</span></span><br><span class="line">    <span class="function"><span class="keyword">void</span> <span class="keyword">operator</span> <span class="title">delete</span><span class="params">(<span class="keyword">void</span> *ptr)</span> </span>&#123;&#125; <span class="comment">// 重载了 new 就需要重载 delete</span></span><br><span class="line"><span class="keyword">public</span>:</span><br><span class="line">    <span class="built_in">A</span>() &#123;&#125;</span><br><span class="line">    ~<span class="built_in">A</span>() &#123;&#125;</span><br><span class="line">&#125;;</span><br></pre></td></tr></table></figure>
</li>
</ul>
<h2 id="7-内存对齐"><a class="markdownIt-Anchor" href="#7-内存对齐"></a> 7、内存对齐</h2>
<p>面试高频指数：2星</p>
<hr>
<p><strong>什么是内存对齐？内存对齐的原则？为什么要进行内存对齐，有什么优点？</strong></p>
<p>内存对齐：编译器将程序中的每个“数据单元”安排在字的整数倍的地址指向的内存之中</p>
<p>内存对齐的原则：</p>
<ol>
<li>结构体变量的首地址能够被其最宽基本类型成员大小与对齐基数中的较小者所整除；</li>
<li>结构体每个成员相对于结构体首地址的偏移量（offset）都是该成员大小与对齐基数中的较小者的整数倍，如有需要编译器会在成员之间加上填充字节（internal padding）；</li>
<li>结构体的总大小为结构体最宽基本类型成员大小与对齐基数中的较小者的整数倍，如有需要编译器会在最末一个成员之后加上填充字节（internal padding）。</li>
</ol>
<p>实例：</p>
<figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">/*</span></span><br><span class="line"><span class="comment">说明：程序是在 64 位编译器下测试的</span></span><br><span class="line"><span class="comment">*/</span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;iostream&gt;</span></span></span><br><span class="line"></span><br><span class="line"><span class="keyword">using</span> <span class="keyword">namespace</span> std;</span><br><span class="line"></span><br><span class="line"><span class="class"><span class="keyword">struct</span> <span class="title">A</span></span></span><br><span class="line"><span class="class">&#123;</span></span><br><span class="line">    <span class="keyword">short</span> var; <span class="comment">// 2 字节</span></span><br><span class="line">    <span class="keyword">int</span> var1;  <span class="comment">// 8 字节 （内存对齐原则：填充 2 个字节） 2 (short) + 2 (填充) + 4 (int)= 8</span></span><br><span class="line">    <span class="keyword">long</span> var2; <span class="comment">// 12 字节 8 + 4 (long) = 12</span></span><br><span class="line">    <span class="keyword">char</span> var3; <span class="comment">// 16 字节 （内存对齐原则：填充 3 个字节）12 + 1 (char) + 3 (填充) = 16</span></span><br><span class="line">    string s;  <span class="comment">// 48 字节 16 + 32 (string) = 48</span></span><br><span class="line">&#125;;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">int</span> <span class="title">main</span><span class="params">()</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">    <span class="keyword">short</span> var;</span><br><span class="line">    <span class="keyword">int</span> var1;</span><br><span class="line">    <span class="keyword">long</span> var2;</span><br><span class="line">    <span class="keyword">char</span> var3;</span><br><span class="line">    string s;</span><br><span class="line">    A ex1;</span><br><span class="line">    cout &lt;&lt; <span class="built_in"><span class="keyword">sizeof</span></span>(var) &lt;&lt; endl;  <span class="comment">// 2 short</span></span><br><span class="line">    cout &lt;&lt; <span class="built_in"><span class="keyword">sizeof</span></span>(var1) &lt;&lt; endl; <span class="comment">// 4 int</span></span><br><span class="line">    cout &lt;&lt; <span class="built_in"><span class="keyword">sizeof</span></span>(var2) &lt;&lt; endl; <span class="comment">// 4 long</span></span><br><span class="line">    cout &lt;&lt; <span class="built_in"><span class="keyword">sizeof</span></span>(var3) &lt;&lt; endl; <span class="comment">// 1 char</span></span><br><span class="line">    cout &lt;&lt; <span class="built_in"><span class="keyword">sizeof</span></span>(s) &lt;&lt; endl;    <span class="comment">// 32 string</span></span><br><span class="line">    cout &lt;&lt; <span class="built_in"><span class="keyword">sizeof</span></span>(ex1) &lt;&lt; endl;  <span class="comment">// 48 struct</span></span><br><span class="line">    <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>进行内存对齐的原因：（主要是硬件设备方面的问题）</p>
<ol>
<li>某些硬件设备只能存取对齐数据，存储非对齐的数据可能会引发异常；</li>
<li>某些硬件设备不能保证在存取非对齐数据的时候的操作是原子操作；</li>
<li>相比于存储对齐的数据，存储非对齐的数据需要花费更多的时间；</li>
<li>某些处理器虽然支持非对齐数据的访问，但会引发对齐陷阱（alignment trap）；</li>
<li>某些硬件设备只支持简单数据指令非对齐存取，不支持复杂数据指令的非对齐存取。</li>
</ol>
<p>内存对齐的优点：</p>
<ol>
<li>便于在不同的平台之间进行移植，因为有些硬件平台不能够支持任意地址的数据访问，只能在某些地址处取某些特定的数据，否则会抛出异常；</li>
<li>提高内存的访问效率，因为CPU在读取内存时，是一块一块地读取。</li>
</ol>
<p>更多解读：<a target="_blank" rel="noopener" href="https://blog.csdn.net/a2111221996/article/details/104899063/">https://blog.csdn.net/a2111221996/article/details/104899063/</a></p>
<h2 id="8-类的大小"><a class="markdownIt-Anchor" href="#8-类的大小"></a> 8、类的大小</h2>
<p>面试高频指数：2星</p>
<hr>
<p><strong>类大小的计算</strong></p>
<p>说明：类的大小是指类的实例化对象的大小，用 <code>sizeof</code> 对类型名操作时，结果是该类型的对象的大小。</p>
<p>计算原则：</p>
<ul>
<li>遵循结构体的对齐原则；</li>
<li>与普通成员变量有关，与成员函数和静态成员无关。即普通成员函数，静态成员函数，静态数据成员，静态常量数据成员均对类的大小无影响。因为静态数据成员被类的对象共享，并不属于哪个具体的对象。</li>
<li>虚函数对类的大小有影响，是因为虚函数表指针的影响。</li>
<li>虚继承对类的大小有影响，是因为虚基表指针带来的影响。</li>
<li>空类的大小是一个特殊情况，空类的大小为1，当用 <code>new</code> 来创建一个空类的对象时，为了保证不同对象的地址不同，空类也占用存储空间。</li>
</ul>
<p><strong>实例</strong></p>
<p>简单情况和空类情况</p>
<figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">/*</span></span><br><span class="line"><span class="comment">说明：程序是在 64 位编译器下测试的</span></span><br><span class="line"><span class="comment">*/</span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;iostream&gt;</span></span></span><br><span class="line"></span><br><span class="line"><span class="keyword">using</span> <span class="keyword">namespace</span> std;</span><br><span class="line"></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">A</span></span></span><br><span class="line"><span class="class">&#123;</span></span><br><span class="line"><span class="keyword">private</span>:</span><br><span class="line">    <span class="keyword">static</span> <span class="keyword">int</span> s_var; <span class="comment">// 不影响类的大小</span></span><br><span class="line">    <span class="keyword">const</span> <span class="keyword">int</span> c_var;  <span class="comment">// 4 字节</span></span><br><span class="line">    <span class="keyword">int</span> var;          <span class="comment">// 8 字节 4 + 4 (int) = 8</span></span><br><span class="line">    <span class="keyword">char</span> var1;        <span class="comment">// 12 字节 8 + 1 (char) + 3 (填充) = 12</span></span><br><span class="line"><span class="keyword">public</span>:</span><br><span class="line">    <span class="built_in">A</span>(<span class="keyword">int</span> temp) : <span class="built_in">c_var</span>(temp) &#123;&#125; <span class="comment">// 不影响类的大小</span></span><br><span class="line">    ~<span class="built_in">A</span>() &#123;&#125;                    <span class="comment">// 不影响类的大小</span></span><br><span class="line">&#125;;</span><br><span class="line"></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">B</span></span></span><br><span class="line"><span class="class">&#123;</span></span><br><span class="line">&#125;;</span><br><span class="line"><span class="function"><span class="keyword">int</span> <span class="title">main</span><span class="params">()</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">    <span class="function">A <span class="title">ex1</span><span class="params">(<span class="number">4</span>)</span></span>;</span><br><span class="line">    B ex2;</span><br><span class="line">    cout &lt;&lt; <span class="built_in"><span class="keyword">sizeof</span></span>(ex1) &lt;&lt; endl; <span class="comment">// 12 字节</span></span><br><span class="line">    cout &lt;&lt; <span class="built_in"><span class="keyword">sizeof</span></span>(ex2) &lt;&lt; endl; <span class="comment">// 1 字节</span></span><br><span class="line">    <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>带有虚函数的情况：（注意：虚函数的个数并不影响所占内存的大小，因为类对象的内存中只保存了指向虚函数表的指针。）</p>
<figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">/*</span></span><br><span class="line"><span class="comment">说明：程序是在 64 位编译器下测试的</span></span><br><span class="line"><span class="comment">*/</span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;iostream&gt;</span></span></span><br><span class="line"></span><br><span class="line"><span class="keyword">using</span> <span class="keyword">namespace</span> std;</span><br><span class="line"></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">A</span></span></span><br><span class="line"><span class="class">&#123;</span></span><br><span class="line"><span class="keyword">private</span>:</span><br><span class="line">    <span class="keyword">static</span> <span class="keyword">int</span> s_var; <span class="comment">// 不影响类的大小</span></span><br><span class="line">    <span class="keyword">const</span> <span class="keyword">int</span> c_var;  <span class="comment">// 4 字节</span></span><br><span class="line">    <span class="keyword">int</span> var;          <span class="comment">// 8 字节 4 + 4 (int) = 8</span></span><br><span class="line">    <span class="keyword">char</span> var1;        <span class="comment">// 12 字节 8 + 1 (char) + 3 (填充) = 12</span></span><br><span class="line"><span class="keyword">public</span>:</span><br><span class="line">    <span class="built_in">A</span>(<span class="keyword">int</span> temp) : <span class="built_in">c_var</span>(temp) &#123;&#125; <span class="comment">// 不影响类的大小</span></span><br><span class="line">    ~<span class="built_in">A</span>() &#123;&#125;                      <span class="comment">// 不影响类的大小</span></span><br><span class="line">    <span class="function"><span class="keyword">virtual</span> <span class="keyword">void</span> <span class="title">f</span><span class="params">()</span> </span>&#123; cout &lt;&lt; <span class="string">&quot;A::f&quot;</span> &lt;&lt; endl; &#125;</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">virtual</span> <span class="keyword">void</span> <span class="title">g</span><span class="params">()</span> </span>&#123; cout &lt;&lt; <span class="string">&quot;A::g&quot;</span> &lt;&lt; endl; &#125;</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">virtual</span> <span class="keyword">void</span> <span class="title">h</span><span class="params">()</span> </span>&#123; cout &lt;&lt; <span class="string">&quot;A::h&quot;</span> &lt;&lt; endl; &#125; <span class="comment">// 24 字节 12 + 4 (填充) + 8 (指向虚函数的指针) = 24</span></span><br><span class="line">&#125;;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">int</span> <span class="title">main</span><span class="params">()</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">    <span class="function">A <span class="title">ex1</span><span class="params">(<span class="number">4</span>)</span></span>;</span><br><span class="line">    A *p;</span><br><span class="line">    cout &lt;&lt; <span class="built_in"><span class="keyword">sizeof</span></span>(p) &lt;&lt; endl;   <span class="comment">// 8 字节 注意：指针所占的空间和指针指向的数据类型无关</span></span><br><span class="line">    cout &lt;&lt; <span class="built_in"><span class="keyword">sizeof</span></span>(ex1) &lt;&lt; endl; <span class="comment">// 24 字节</span></span><br><span class="line">    <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<h2 id="9-什么是内存泄漏"><a class="markdownIt-Anchor" href="#9-什么是内存泄漏"></a> 9、什么是内存泄漏</h2>
<p>面试高频指数：四星</p>
<hr>
<p><strong>内存泄漏：</strong> 由于疏忽或错误导致的程序未能释放已经不再使用的内存。</p>
<p>进一步解释：</p>
<ul>
<li>并非指内存从物理上消失，而是指程序在运行过程中，由于疏忽或错误而失去了对该内存的控制，从而造成了内存的浪费。</li>
<li>常指堆内存泄漏，因为堆是动态分配的，而且是用户来控制的，如果使用不当，会产生内存泄漏。</li>
<li>使用 <code>malloc</code>、<code>calloc</code>、<code>realloc</code>、<code>new</code> 等分配内存时，使用完后要调用相应的 <code>free</code> 或 <code>delete</code> 释放内存，否则这块内存就会造成内存泄漏。</li>
<li>指针重新赋值</li>
</ul>
<figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">char</span> *p = (<span class="keyword">char</span> *)<span class="built_in">malloc</span>(<span class="number">10</span>);</span><br><span class="line"><span class="keyword">char</span> *p1 = (<span class="keyword">char</span> *)<span class="built_in">malloc</span>(<span class="number">10</span>);</span><br><span class="line">p = np;</span><br></pre></td></tr></table></figure>
<p>开始时，指针 <code>p</code> 和 <code>p1</code> 分别指向一块内存空间，但指针 <code>p</code> 被重新赋值，导致 <code>p</code> 初始时指向的那块内存空间无法找到，从而发生了内存泄漏。</p>
<h2 id="10-怎么防止内存泄漏内存泄漏检测工具的原理"><a class="markdownIt-Anchor" href="#10-怎么防止内存泄漏内存泄漏检测工具的原理"></a> 10、怎么防止内存泄漏？内存泄漏检测工具的原理？</h2>
<p>面试高频指数：三星</p>
<hr>
<p><strong>防止内存泄漏的方法：</strong></p>
<ol>
<li>
<p>内部封装：将内存的分配和释放封装到类中，在构造的时候申请内存，析构的时候释放内存。</p>
 <figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;iostream&gt;</span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;cstring&gt;</span></span></span><br><span class="line"></span><br><span class="line"><span class="keyword">using</span> <span class="keyword">namespace</span> std;</span><br><span class="line"></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">A</span></span></span><br><span class="line"><span class="class">&#123;</span></span><br><span class="line"><span class="keyword">private</span>:</span><br><span class="line">    <span class="keyword">char</span> *p;</span><br><span class="line">    <span class="keyword">unsigned</span> <span class="keyword">int</span> p_size;</span><br><span class="line"></span><br><span class="line"><span class="keyword">public</span>:</span><br><span class="line">    <span class="built_in">A</span>(<span class="keyword">unsigned</span> <span class="keyword">int</span> n = <span class="number">1</span>) <span class="comment">// 构造函数中分配内存空间</span></span><br><span class="line">    &#123;</span><br><span class="line">        p = <span class="keyword">new</span> <span class="keyword">char</span>[n];</span><br><span class="line">        p_size = n;</span><br><span class="line">    &#125;;</span><br><span class="line">    ~<span class="built_in">A</span>() <span class="comment">// 析构函数中释放内存空间</span></span><br><span class="line">    &#123;</span><br><span class="line">        <span class="keyword">if</span> (p != <span class="literal">NULL</span>)</span><br><span class="line">        &#123;</span><br><span class="line">            <span class="keyword">delete</span>[] p; <span class="comment">// 删除字符数组</span></span><br><span class="line">            p = <span class="literal">NULL</span>;   <span class="comment">// 防止出现野指针</span></span><br><span class="line">        &#125;</span><br><span class="line">    &#125;;</span><br><span class="line">    <span class="function"><span class="keyword">char</span> *<span class="title">GetPointer</span><span class="params">()</span></span></span><br><span class="line"><span class="function">    </span>&#123;</span><br><span class="line">        <span class="keyword">return</span> p;</span><br><span class="line">    &#125;;</span><br><span class="line">&#125;;</span><br><span class="line"><span class="function"><span class="keyword">void</span> <span class="title">fun</span><span class="params">()</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">    <span class="function">A <span class="title">ex</span><span class="params">(<span class="number">100</span>)</span></span>;</span><br><span class="line">    <span class="keyword">char</span> *p = ex.<span class="built_in">GetPointer</span>();</span><br><span class="line">    <span class="built_in">strcpy</span>(p, <span class="string">&quot;Test&quot;</span>);</span><br><span class="line">    cout &lt;&lt; p &lt;&lt; endl;</span><br><span class="line">&#125;</span><br><span class="line"><span class="function"><span class="keyword">int</span> <span class="title">main</span><span class="params">()</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">    <span class="built_in">fun</span>();</span><br><span class="line">    <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>说明：这样做并不是最佳的做法，在类的对象复制时，程序会出现同一块内存空间释放两次的情况，请看如下程序：</p>
 <figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">void</span> <span class="title">fun1</span><span class="params">()</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">    <span class="function">A <span class="title">ex</span><span class="params">(<span class="number">100</span>)</span></span>;</span><br><span class="line">    A ex1 = ex; </span><br><span class="line">    <span class="keyword">char</span> *p = ex.<span class="built_in">GetPointer</span>();</span><br><span class="line">    <span class="built_in">strcpy</span>(p, <span class="string">&quot;Test&quot;</span>);</span><br><span class="line">    cout &lt;&lt; p &lt;&lt; endl;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>简单解释：对于 <code>fun1</code> 这个函数中定义的两个类的对象而言，在离开该函数的作用域时，会两次调用析构函数来释放空间，但是这两个对象指向的是同一块内存空间，所以导致同一块内存空间被释放两次，可以通过增加计数机制来避免这种情况，看如下程序：</p>
 <figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;iostream&gt;</span></span></span><br><span class="line"> <span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;cstring&gt;</span></span></span><br><span class="line"></span><br><span class="line"> <span class="keyword">using</span> <span class="keyword">namespace</span> std;</span><br><span class="line"> <span class="class"><span class="keyword">class</span> <span class="title">A</span></span></span><br><span class="line"><span class="class"> &#123;</span></span><br><span class="line"> <span class="keyword">private</span>:</span><br><span class="line">     <span class="keyword">char</span> *p;</span><br><span class="line">     <span class="keyword">unsigned</span> <span class="keyword">int</span> p_size;</span><br><span class="line">     <span class="keyword">int</span> *p_count; <span class="comment">// 计数变量 [自己理解：同一个地址在多个实例之间共享,如果是单独的int，则每个实例有个单独的变量，起不到计数变量的作用]</span></span><br><span class="line"> <span class="keyword">public</span>:</span><br><span class="line">     <span class="built_in">A</span>(<span class="keyword">unsigned</span> <span class="keyword">int</span> n = <span class="number">1</span>) <span class="comment">// 在构造函数中申请内存</span></span><br><span class="line">     &#123;</span><br><span class="line">         p = <span class="keyword">new</span> <span class="keyword">char</span>[n];</span><br><span class="line">         p_size = n;</span><br><span class="line">         p_count = <span class="keyword">new</span> <span class="keyword">int</span>;</span><br><span class="line">         *p_count = <span class="number">1</span>;</span><br><span class="line">         cout &lt;&lt; <span class="string">&quot;count is : &quot;</span> &lt;&lt; *p_count &lt;&lt; endl;</span><br><span class="line">     &#125;;</span><br><span class="line">     <span class="built_in">A</span>(<span class="keyword">const</span> A &amp;temp)</span><br><span class="line">     &#123;</span><br><span class="line">         p = temp.p;</span><br><span class="line">         p_size = temp.p_size;</span><br><span class="line">         p_count = temp.p_count;</span><br><span class="line">         (*p_count)++; <span class="comment">// 复制时，计数变量 +1</span></span><br><span class="line">         cout &lt;&lt; <span class="string">&quot;count is : &quot;</span> &lt;&lt; *p_count &lt;&lt; endl;</span><br><span class="line">     &#125;</span><br><span class="line">     ~<span class="built_in">A</span>()</span><br><span class="line">     &#123;</span><br><span class="line">         (*p_count)--; <span class="comment">// 析构时，计数变量 -1</span></span><br><span class="line">         cout &lt;&lt; <span class="string">&quot;count is : &quot;</span> &lt;&lt; *p_count &lt;&lt; endl; </span><br><span class="line"></span><br><span class="line">         <span class="keyword">if</span> (*p_count == <span class="number">0</span>) <span class="comment">// 只有当计数变量为 0 的时候才会释放该块内存空间</span></span><br><span class="line">         &#123;</span><br><span class="line">             cout &lt;&lt; <span class="string">&quot;buf is deleted&quot;</span> &lt;&lt; endl;</span><br><span class="line">             <span class="keyword">if</span> (p != <span class="literal">NULL</span>) </span><br><span class="line">             &#123;</span><br><span class="line">                 <span class="keyword">delete</span>[] p; <span class="comment">// 删除字符数组</span></span><br><span class="line">                 p = <span class="literal">NULL</span>;   <span class="comment">// 防止出现野指针</span></span><br><span class="line">                 <span class="keyword">if</span> (p_count != <span class="literal">NULL</span>)</span><br><span class="line">                 &#123;</span><br><span class="line">                     <span class="keyword">delete</span> p_count;</span><br><span class="line">                     p_count = <span class="literal">NULL</span>;</span><br><span class="line">                 &#125;</span><br><span class="line">             &#125;</span><br><span class="line">         &#125;</span><br><span class="line">     &#125;;</span><br><span class="line">     <span class="function"><span class="keyword">char</span> *<span class="title">GetPointer</span><span class="params">()</span></span></span><br><span class="line"><span class="function">     </span>&#123;</span><br><span class="line">         <span class="keyword">return</span> p;</span><br><span class="line">     &#125;;</span><br><span class="line"> &#125;;</span><br><span class="line"> <span class="function"><span class="keyword">void</span> <span class="title">fun</span><span class="params">()</span></span></span><br><span class="line"><span class="function"> </span>&#123;</span><br><span class="line">     <span class="function">A <span class="title">ex</span><span class="params">(<span class="number">100</span>)</span></span>;</span><br><span class="line">     <span class="keyword">char</span> *p = ex.<span class="built_in">GetPointer</span>();</span><br><span class="line">     <span class="built_in">strcpy</span>(p, <span class="string">&quot;Test&quot;</span>);</span><br><span class="line">     cout &lt;&lt; p &lt;&lt; endl;</span><br><span class="line"></span><br><span class="line">     A ex1 = ex; <span class="comment">// 此时计数变量会 +1</span></span><br><span class="line">     cout &lt;&lt; <span class="string">&quot;ex1.p = &quot;</span> &lt;&lt; ex1.<span class="built_in">GetPointer</span>() &lt;&lt; endl;</span><br><span class="line"> &#125;</span><br><span class="line"> <span class="function"><span class="keyword">int</span> <span class="title">main</span><span class="params">()</span></span></span><br><span class="line"><span class="function"> </span>&#123;</span><br><span class="line">     <span class="built_in">fun</span>();</span><br><span class="line">     <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line"> &#125;</span><br></pre></td></tr></table></figure>
<p>程序运行结果：</p>
 <figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">count is : <span class="number">1</span></span><br><span class="line">Test</span><br><span class="line">count is : <span class="number">2</span></span><br><span class="line">ex1.p = Test</span><br><span class="line">count is : <span class="number">1</span></span><br><span class="line">count is : <span class="number">0</span></span><br><span class="line">buf is deleted</span><br></pre></td></tr></table></figure>
<p>解释下：程序运行结果的倒数2、3行是调用两次析构函数时进行的操作，在第二次析构函数时，进行内存空间的释放，从而会有倒数第 1 行的输出结果。</p>
</li>
<li>
<p>智能指针</p>
<p>智能指针是 C++ 中已经对内存泄漏封装好了的一个工具，可以直接拿来使用，将在下一个问题中对智能指针进行详细的讲解。</p>
</li>
</ol>
<p><strong>内存泄漏检测工具的实现原理</strong>：</p>
<p>内存检测工具有很多，这里重点介绍下 <code>valgrind</code>。</p>
<p><img src="https://gitee.com/maureen-liu/typora-image/raw/master/typora-image/1612687346-kyLXKn-image.png" alt="image.png"></p>
<p><code>valgrind</code> 是一套 Linux 下，开放源代码（GPL V2）的仿真调试工具的集合，包括以下工具：</p>
<ul>
<li><code>Memcheck</code>：内存检查器（valgrind 应用最广泛的工具），能够发现开发中绝大多数内存错误的使用情况，比如：使用未初始化的内存，使用已经释放了的内存，内存访问越界等。</li>
<li><code>Callgrind</code>：检查程序中函数调用过程中出现的问题。</li>
<li><code>Cachegrind</code>：检查程序中缓存使用出现的问题。</li>
<li><code>Helgrind</code>：检查多线程程序中出现的竞争问题。</li>
<li><code>Massif</code>：检查程序中堆栈使用中出现的问题。</li>
<li><code>Extension</code>：可以利用 core 提供的功能，自己编写特定的内存调试工具。</li>
</ul>
<p><code>Memcheck</code>能够检测出内存问题，关键在于其建立了两个全局表：</p>
<ul>
<li><code>Valid-Value</code>表：对于进程的整个地址空间中的每一个字节（byte），都有与之对应的 8 个bits；对于 CPU 的每个寄存器，也有一个与之对应的 bit 向量。这些 bits 负责记录该字节或者寄存器值是否具有有效的、已初始化的值。</li>
<li><code>Valid-Address</code>表：对于进程整个地址空间中的每一个字节（byte），还有与之对应的 1 个 bit，负责记录该地址是否能够被读写。</li>
</ul>
<p>检测原理：</p>
<ul>
<li>当要读写内存中某个字节时，首先检查这个字节对应的 <code>Valid-Address</code> 表中对应的 bit。如果该 bit 显示该位置是无效位置，Memcheck 则报告读写错误。</li>
<li>内核（core）类似于一个虚拟的 CPU 环境，这样当内存中的某个字节被加载到真实的 CPU 中时，该字节在 Valid-Value 表对应的 bits 也被加载到虚拟的 CPU 环境中。一旦寄存器中的值，被用来产生内存地址，或者该值能够影响程序输出，则 Memcheck 会检查 Valid-Value 表对应的 bits，如果该值尚未初始化，则会报告使用未初始化内存错误。</li>
</ul>
<h2 id="11-智能指针有哪几种智能指针的实现原理"><a class="markdownIt-Anchor" href="#11-智能指针有哪几种智能指针的实现原理"></a> 11、智能指针有哪几种？智能指针的实现原理？</h2>
<p>面试高频指数：五星</p>
<hr>
<p>智能指针是为了解决动态内存分配时带来的内存泄漏以及多次释放同一块内存空间而提出的。C++11 中封装在了 <code>&lt;memory&gt;</code> 头文件中。</p>
<p>C++11 中智能指针包括以下三种：</p>
<ul>
<li><strong>共享指针（shared_ptr)</strong>：资源可以被多个指针共享，使用计数机制表明资源被几个指针共享。通过 <code>use_count()</code> 查看资源的所有者的个数，可以通过 <code>unique_ptr</code>、<code>weak_ptr</code> 来构造，调用 <code>release()</code> 释放资源的所有权，计数减一，当计数减为 0 时，会自动释放内存空间，从而避免了内存泄漏。</li>
<li><strong>独占指针（unique_ptr)</strong>：独享所有权的智能指针，资源只能被一个指针占有，该指针不能拷贝构造和赋值。但可以进行移动构造和移动赋值构造（调用 <code>move()</code> 函数)，即一个 <code>unique_ptr</code> 对象赋值给另一个 <code>unique_ptr</code> 对象，可以通过该方法进行赋值。</li>
<li><strong>弱指针（weak_ptr)</strong>：指向 <code>shared_ptr</code> 指向的对象，能够解决由 shared_ptr 带来的循环引用问题。</li>
</ul>
<p><strong>智能指针的实现原理：</strong> 计数原理。</p>
<figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;iostream&gt;</span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;memory&gt;</span></span></span><br><span class="line"></span><br><span class="line"><span class="keyword">template</span> &lt;<span class="keyword">typename</span> T&gt;</span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">SmartPtr</span></span></span><br><span class="line"><span class="class">&#123;</span></span><br><span class="line"><span class="keyword">private</span> : </span><br><span class="line">	T *_ptr;</span><br><span class="line">	<span class="keyword">size_t</span> *_count;</span><br><span class="line"></span><br><span class="line"><span class="keyword">public</span>:</span><br><span class="line">	<span class="built_in">SmartPtr</span>(T *ptr = <span class="literal">nullptr</span>) : _ptr(ptr)</span><br><span class="line">	&#123;</span><br><span class="line">		<span class="keyword">if</span> (_ptr)</span><br><span class="line">		&#123;</span><br><span class="line">			_count = <span class="keyword">new</span> <span class="built_in">size_t</span>(<span class="number">1</span>);</span><br><span class="line">		&#125;</span><br><span class="line">		<span class="keyword">else</span></span><br><span class="line">		&#123;</span><br><span class="line">			_count = <span class="keyword">new</span> <span class="built_in">size_t</span>(<span class="number">0</span>);</span><br><span class="line">		&#125;</span><br><span class="line">	&#125;</span><br><span class="line"></span><br><span class="line">	~<span class="built_in">SmartPtr</span>()</span><br><span class="line">	&#123;</span><br><span class="line">		(*<span class="keyword">this</span>-&gt;_count)--;</span><br><span class="line">		<span class="keyword">if</span> (*<span class="keyword">this</span>-&gt;_count == <span class="number">0</span>)</span><br><span class="line">		&#123;</span><br><span class="line">			<span class="keyword">delete</span> <span class="keyword">this</span>-&gt;_ptr;</span><br><span class="line">			<span class="keyword">delete</span> <span class="keyword">this</span>-&gt;_count;</span><br><span class="line">		&#125;</span><br><span class="line">	&#125;</span><br><span class="line"></span><br><span class="line">	<span class="built_in">SmartPtr</span>(<span class="keyword">const</span> SmartPtr &amp;ptr) <span class="comment">// 拷贝构造：计数 +1</span></span><br><span class="line">	&#123;</span><br><span class="line">		<span class="keyword">if</span> (<span class="keyword">this</span> != &amp;ptr)</span><br><span class="line">		&#123;</span><br><span class="line">			<span class="keyword">this</span>-&gt;_ptr = ptr._ptr;</span><br><span class="line">			<span class="keyword">this</span>-&gt;_count = ptr._count;</span><br><span class="line">			(*<span class="keyword">this</span>-&gt;_count)++;</span><br><span class="line">		&#125;</span><br><span class="line">	&#125;</span><br><span class="line"></span><br><span class="line">	SmartPtr &amp;<span class="keyword">operator</span>=(<span class="keyword">const</span> SmartPtr &amp;ptr) <span class="comment">// 赋值运算符重载 </span></span><br><span class="line">	&#123;</span><br><span class="line">		<span class="keyword">if</span> (<span class="keyword">this</span>-&gt;_ptr == ptr._ptr)</span><br><span class="line">		&#123;</span><br><span class="line">			<span class="keyword">return</span> *<span class="keyword">this</span>;</span><br><span class="line">		&#125;</span><br><span class="line">		<span class="keyword">if</span> (<span class="keyword">this</span>-&gt;_ptr) <span class="comment">// 将当前的 ptr 指向的原来的空间的计数 -1</span></span><br><span class="line">		&#123;</span><br><span class="line">			(*<span class="keyword">this</span>-&gt;_count)--;</span><br><span class="line">			<span class="keyword">if</span> (<span class="keyword">this</span>-&gt;_count == <span class="number">0</span>)</span><br><span class="line">			&#123;</span><br><span class="line">				<span class="keyword">delete</span> <span class="keyword">this</span>-&gt;_ptr;</span><br><span class="line">				<span class="keyword">delete</span> <span class="keyword">this</span>-&gt;_count;</span><br><span class="line">			&#125;</span><br><span class="line">		&#125;</span><br><span class="line">		<span class="keyword">this</span>-&gt;_ptr = ptr._ptr;</span><br><span class="line">		<span class="keyword">this</span>-&gt;_count = ptr._count;</span><br><span class="line">		(*<span class="keyword">this</span>-&gt;_count)++; <span class="comment">// 此时 ptr 指向了新赋值的空间，该空间的计数 +1</span></span><br><span class="line">		<span class="keyword">return</span> *<span class="keyword">this</span>;</span><br><span class="line">	&#125;</span><br><span class="line"></span><br><span class="line">	T &amp;<span class="keyword">operator</span>*()</span><br><span class="line">	&#123;</span><br><span class="line">		<span class="built_in">assert</span>(<span class="keyword">this</span>-&gt;_ptr == <span class="literal">nullptr</span>);</span><br><span class="line">		<span class="keyword">return</span> *(<span class="keyword">this</span>-&gt;_ptr);</span><br><span class="line">	&#125;</span><br><span class="line"></span><br><span class="line">	T *<span class="keyword">operator</span>-&gt;()</span><br><span class="line">	&#123;</span><br><span class="line">		<span class="built_in">assert</span>(<span class="keyword">this</span>-&gt;_ptr == <span class="literal">nullptr</span>);</span><br><span class="line">		<span class="keyword">return</span> <span class="keyword">this</span>-&gt;_ptr;</span><br><span class="line">	&#125;</span><br><span class="line"></span><br><span class="line">	<span class="function"><span class="keyword">size_t</span> <span class="title">use_count</span><span class="params">()</span></span></span><br><span class="line"><span class="function">	</span>&#123;</span><br><span class="line">		<span class="keyword">return</span> *<span class="keyword">this</span>-&gt;count;</span><br><span class="line">	&#125;</span><br><span class="line">&#125;;</span><br></pre></td></tr></table></figure>
<h2 id="12-一个-unique_ptr-怎么赋值给另一个-unique_ptr-对象"><a class="markdownIt-Anchor" href="#12-一个-unique_ptr-怎么赋值给另一个-unique_ptr-对象"></a> 12、一个 unique_ptr 怎么赋值给另一个 unique_ptr 对象？</h2>
<p>面试高频指数：2星</p>
<hr>
<p>借助 <code>std::move()</code> 可以实现将一个 <code>unique_ptr</code> 对象赋值给另一个 <code>unique_ptr</code> 对象，其目的是实现所有权的转移。</p>
<figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// A 作为一个类 </span></span><br><span class="line"><span class="function">std::unique_ptr&lt;A&gt; <span class="title">ptr1</span><span class="params">(<span class="keyword">new</span> A())</span></span>;</span><br><span class="line">std::unique_ptr&lt;A&gt; ptr2 = std::<span class="built_in">move</span>(ptr1);</span><br></pre></td></tr></table></figure>
<h2 id="13-使用智能指针会出现什么问题怎么解决"><a class="markdownIt-Anchor" href="#13-使用智能指针会出现什么问题怎么解决"></a> 13、使用智能指针会出现什么问题？怎么解决？</h2>
<p>面试高频指数：五星</p>
<hr>
<p><strong>智能指针可能出现的问题：循环引用</strong></p>
<p>在如下例子中定义了两个类 <code>Parent</code>、<code>Child</code>，在两个类中分别定义另一个类的对象的共享指针，由于在程序结束后，两个指针互相指向对方的内存空间，导致内存无法释放。</p>
<figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;iostream&gt;</span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;memory&gt;</span></span></span><br><span class="line"></span><br><span class="line"><span class="keyword">using</span> <span class="keyword">namespace</span> std;</span><br><span class="line"></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Child</span>;</span></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Parent</span>;</span></span><br><span class="line"></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Parent</span> &#123;</span></span><br><span class="line"><span class="keyword">private</span>:</span><br><span class="line">    shared_ptr&lt;Child&gt; ChildPtr;</span><br><span class="line"><span class="keyword">public</span>:</span><br><span class="line">    <span class="function"><span class="keyword">void</span> <span class="title">setChild</span><span class="params">(shared_ptr&lt;Child&gt; child)</span> </span>&#123;</span><br><span class="line">        <span class="keyword">this</span>-&gt;ChildPtr = child;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">void</span> <span class="title">doSomething</span><span class="params">()</span> </span>&#123;</span><br><span class="line">        <span class="keyword">if</span> (<span class="keyword">this</span>-&gt;ChildPtr.<span class="built_in">use_count</span>()) &#123;</span><br><span class="line"></span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    ~<span class="built_in">Parent</span>() &#123;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;;</span><br><span class="line"></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Child</span> &#123;</span></span><br><span class="line"><span class="keyword">private</span>:</span><br><span class="line">    shared_ptr&lt;Parent&gt; ParentPtr;</span><br><span class="line"><span class="keyword">public</span>:</span><br><span class="line">    <span class="function"><span class="keyword">void</span> <span class="title">setPartent</span><span class="params">(shared_ptr&lt;Parent&gt; parent)</span> </span>&#123;</span><br><span class="line">        <span class="keyword">this</span>-&gt;ParentPtr = parent;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="function"><span class="keyword">void</span> <span class="title">doSomething</span><span class="params">()</span> </span>&#123;</span><br><span class="line">        <span class="keyword">if</span> (<span class="keyword">this</span>-&gt;ParentPtr.<span class="built_in">use_count</span>()) &#123;</span><br><span class="line"></span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">    ~<span class="built_in">Child</span>() &#123;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">int</span> <span class="title">main</span><span class="params">()</span> </span>&#123;</span><br><span class="line">    weak_ptr&lt;Parent&gt; wpp;</span><br><span class="line">    weak_ptr&lt;Child&gt; wpc;</span><br><span class="line">    &#123;</span><br><span class="line">        <span class="function">shared_ptr&lt;Parent&gt; <span class="title">p</span><span class="params">(<span class="keyword">new</span> Parent)</span></span>;</span><br><span class="line">        <span class="function">shared_ptr&lt;Child&gt; <span class="title">c</span><span class="params">(<span class="keyword">new</span> Child)</span></span>;</span><br><span class="line">        p-&gt;<span class="built_in">setChild</span>(c);</span><br><span class="line">        c-&gt;<span class="built_in">setPartent</span>(p);</span><br><span class="line">        wpp = p;</span><br><span class="line">        wpc = c;</span><br><span class="line">        cout &lt;&lt; p.<span class="built_in">use_count</span>() &lt;&lt; endl; <span class="comment">// 2</span></span><br><span class="line">        cout &lt;&lt; c.<span class="built_in">use_count</span>() &lt;&lt; endl; <span class="comment">// 2</span></span><br><span class="line">    &#125;</span><br><span class="line">    cout &lt;&lt; wpp.<span class="built_in">use_count</span>() &lt;&lt; endl;  <span class="comment">// 1</span></span><br><span class="line">    cout &lt;&lt; wpc.<span class="built_in">use_count</span>() &lt;&lt; endl;  <span class="comment">// 1</span></span><br><span class="line">    <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p><strong>循环引用的解决方法：</strong> <code>weak_ptr</code></p>
<p>循环引用：该被调用的析构函数没有被调用，从而出现了内存泄漏。</p>
<ul>
<li><code>weak_ptr</code> 对被 <code>shared_ptr</code> 管理的对象存在 <strong>非拥有性（弱）引用</strong>，在访问所引用的对象前必须先转化为 <code>shared_ptr</code>；</li>
<li><code>weak_ptr</code> 用来打断 <code>shared_ptr</code> 所管理对象的循环引用问题，若这种环被孤立（没有指向环中的外部共享指针），<code>shared_ptr</code> 引用计数无法抵达 0，内存被泄漏；令环中的指针之一为弱指针可以避免该情况；</li>
<li><code>weak_ptr</code> 用来表达临时所有权的概念，当某个对象只有存在时才需要被访问，而且随时可能被他人删除，可以用<code>weak_ptr</code> 跟踪该对象；需要获得所有权时将其转化为 <code>shared_ptr</code>，此时如果原来的<code>shared_ptr</code> 被销毁，则该对象的生命期被延长至这个临时的 <code>shared_ptr</code> 同样被销毁。</li>
</ul>
<figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;iostream&gt;</span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;memory&gt;</span></span></span><br><span class="line"></span><br><span class="line"><span class="keyword">using</span> <span class="keyword">namespace</span> std;</span><br><span class="line"></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Child</span>;</span></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Parent</span>;</span></span><br><span class="line"></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Parent</span> &#123;</span></span><br><span class="line"><span class="keyword">private</span>:</span><br><span class="line">    <span class="comment">//shared_ptr&lt;Child&gt; ChildPtr;</span></span><br><span class="line">    weak_ptr&lt;Child&gt; ChildPtr;</span><br><span class="line"><span class="keyword">public</span>:</span><br><span class="line">    <span class="function"><span class="keyword">void</span> <span class="title">setChild</span><span class="params">(shared_ptr&lt;Child&gt; child)</span> </span>&#123;</span><br><span class="line">        <span class="keyword">this</span>-&gt;ChildPtr = child;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">void</span> <span class="title">doSomething</span><span class="params">()</span> </span>&#123;</span><br><span class="line">        <span class="comment">//new shared_ptr</span></span><br><span class="line">        <span class="keyword">if</span> (<span class="keyword">this</span>-&gt;ChildPtr.<span class="built_in">lock</span>()) &#123;</span><br><span class="line"></span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    ~<span class="built_in">Parent</span>() &#123;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;;</span><br><span class="line"></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Child</span> &#123;</span></span><br><span class="line"><span class="keyword">private</span>:</span><br><span class="line">    shared_ptr&lt;Parent&gt; ParentPtr;</span><br><span class="line"><span class="keyword">public</span>:</span><br><span class="line">    <span class="function"><span class="keyword">void</span> <span class="title">setPartent</span><span class="params">(shared_ptr&lt;Parent&gt; parent)</span> </span>&#123;</span><br><span class="line">        <span class="keyword">this</span>-&gt;ParentPtr = parent;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="function"><span class="keyword">void</span> <span class="title">doSomething</span><span class="params">()</span> </span>&#123;</span><br><span class="line">        <span class="keyword">if</span> (<span class="keyword">this</span>-&gt;ParentPtr.<span class="built_in">use_count</span>()) &#123;</span><br><span class="line"></span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">    ~<span class="built_in">Child</span>() &#123;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">int</span> <span class="title">main</span><span class="params">()</span> </span>&#123;</span><br><span class="line">    weak_ptr&lt;Parent&gt; wpp;</span><br><span class="line">    weak_ptr&lt;Child&gt; wpc;</span><br><span class="line">    &#123;</span><br><span class="line">        <span class="function">shared_ptr&lt;Parent&gt; <span class="title">p</span><span class="params">(<span class="keyword">new</span> Parent)</span></span>;</span><br><span class="line">        <span class="function">shared_ptr&lt;Child&gt; <span class="title">c</span><span class="params">(<span class="keyword">new</span> Child)</span></span>;</span><br><span class="line">        p-&gt;<span class="built_in">setChild</span>(c);</span><br><span class="line">        c-&gt;<span class="built_in">setPartent</span>(p);</span><br><span class="line">        wpp = p;</span><br><span class="line">        wpc = c;</span><br><span class="line">        cout &lt;&lt; p.<span class="built_in">use_count</span>() &lt;&lt; endl; <span class="comment">// 2</span></span><br><span class="line">        cout &lt;&lt; c.<span class="built_in">use_count</span>() &lt;&lt; endl; <span class="comment">// 1</span></span><br><span class="line">    &#125;</span><br><span class="line">    cout &lt;&lt; wpp.<span class="built_in">use_count</span>() &lt;&lt; endl;  <span class="comment">// 0</span></span><br><span class="line">    cout &lt;&lt; wpc.<span class="built_in">use_count</span>() &lt;&lt; endl;  <span class="comment">// 0</span></span><br><span class="line">    <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<h1 id="二-语言对比"><a class="markdownIt-Anchor" href="#二-语言对比"></a> 二、语言对比</h1>
<h2 id="1-c11-新特性"><a class="markdownIt-Anchor" href="#1-c11-新特性"></a> 1、C++11 新特性</h2>
<p>面试高频指数：四星</p>
<hr>
<p>说明：C++11的新特性有很多，从面试的角度来讲，如果面试官问到该问题，常以该问题作为引子，对面试者提到的知识点进行深入展开提问。面试者尽可能地列举常用的并且熟悉的特性，尽可能地掌握相关原理，下文只是对相关知识点进行了简单的阐述，有关细节还需结合相关知识点的相关问题。</p>
<p>下面对常用的做一下总结：</p>
<ol>
<li>
<p><code>auto</code> 类型推导</p>
<p><code>auto</code> 关键字：自动类型推导，编译器会在 <strong>编译期间</strong> 通过初始值推导出变量的类型，通过 <code>auto</code> 定义的变量必须有初始值。</p>
<p><code>auto</code> 关键字基本的使用语法如下：</p>
 <figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">auto</span> var = val1 + val2; <span class="comment">//根据val1 和 val2 相加的结果推断出 var 的类型</span></span><br></pre></td></tr></table></figure>
<p>注意：编译器推导出来的类型和初始值类型并不完全一致，编译器会适当地改变结果类型使其更符合初始化规则。</p>
</li>
<li>
<p><code>decltype</code> 类型推导</p>
<p><code>decltype</code> 关键字：<code>decltype</code> 是 “declare type” 的缩写，译为“声明类型”。和 <code>auto</code> 的功能一样，都用来在编译时期进行自动类型推导。如果希望从表达式中推断出要定义的变量的类型，但是不想用该表达式的值初始化变量，这时就不能再用 <code>auto</code>。<code>decltype</code> 作用是选择并返回操作数的数据类型。</p>
</li>
</ol>
<p>区别：</p>
<figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">auto</span> var = val1 + val2;</span><br><span class="line"><span class="keyword">decltype</span>(val1 + val2) var1 = <span class="number">0</span>;</span><br></pre></td></tr></table></figure>
<ul>
<li><code>auto</code> 根据 = 右边的初始值 val1 + val2 推导出变量的类型，并将该初始值赋值给变量 var；<code>decltype</code> 根据 val1 + val2 表达式推导出变量的类型，变量的初始值和与表达式的值无关。</li>
<li><code>auto</code> 要求变量必须初始化，因为它是根据初始化的值推导出变量的类型，而<code>decltype</code> 不要求，定义变量的时候可初始化也可不初始化。</li>
</ul>
<ol start="3">
<li>
<p><code>lambda</code>表达式</p>
<p><code>lambda</code>表达式，又被称为 <code>lambda</code>函数或者 <code>lambda</code> 匿名函数。</p>
<p><code>lambda</code> 匿名函数的定义：</p>
 <figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">[capture list] (parameter list) -&gt; <span class="keyword">return</span> type </span><br><span class="line">&#123;</span><br><span class="line">    function body;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>其中：</p>
<ul>
<li>capture list：捕获列表，指 lambda 所在函数中定义的局部变量的列表，通常为空。</li>
<li>return type、parameter list、function body：分别表示返回值类型、参数类型、函数体，和普通函数一样。</li>
</ul>
 <figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;iostream&gt;</span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;algorithm&gt;</span></span></span><br><span class="line"><span class="keyword">using</span> <span class="keyword">namespace</span> std;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">int</span> <span class="title">main</span><span class="params">()</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">    <span class="keyword">int</span> arr[<span class="number">4</span>] = &#123;<span class="number">4</span>, <span class="number">2</span>, <span class="number">3</span>, <span class="number">1</span>&#125;;</span><br><span class="line">    <span class="comment">//对 a 数组中的元素进行升序排序</span></span><br><span class="line">    <span class="built_in">sort</span>(arr, arr+<span class="number">4</span>, [=](<span class="keyword">int</span> x, <span class="keyword">int</span> y) -&gt; <span class="keyword">bool</span>&#123; <span class="keyword">return</span> x &lt; y; &#125; );</span><br><span class="line">    <span class="keyword">for</span>(<span class="keyword">int</span> n : arr)&#123;</span><br><span class="line">        cout &lt;&lt; n &lt;&lt; <span class="string">&quot; &quot;</span>;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
</li>
<li>
<p>范围 <code>for</code> 语句</p>
<p>语法格式：</p>
 <figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">for</span> (declaration : expression) &#123;</span><br><span class="line">    statement</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>参数的含义：</p>
<ul>
<li>expression： 必须是一个序列，例如用花括号括起来的初始值列表、数组、<code>vector</code>、<code>string</code>等，这些类型的共同特点是拥有能返回迭代器的<code>begin</code>、<code>end</code>成员。</li>
<li>declaration：此处定义一个变量，序列中的每一个元素都能转化成该变量的类型，常用<code>auto</code>类型说明符。</li>
</ul>
<p>实例：</p>
 <figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;iostream&gt;</span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;vector&gt;</span></span></span><br><span class="line"><span class="keyword">using</span> <span class="keyword">namespace</span> std;</span><br><span class="line"><span class="function"><span class="keyword">int</span> <span class="title">main</span><span class="params">()</span> </span>&#123;</span><br><span class="line">    <span class="keyword">char</span> arr[] = <span class="string">&quot;hello world!&quot;</span>;</span><br><span class="line">    <span class="keyword">for</span> (<span class="keyword">char</span> c : arr) &#123;</span><br><span class="line">        cout &lt;&lt; c;</span><br><span class="line">    &#125;  </span><br><span class="line">    <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">&#125;</span><br><span class="line"><span class="comment">/*</span></span><br><span class="line"><span class="comment">程序执行结果为：</span></span><br><span class="line"><span class="comment">hello world!</span></span><br><span class="line"><span class="comment">*/</span></span><br></pre></td></tr></table></figure>
</li>
<li>
<p>右值引用</p>
<p>右值引用：绑定到右值的引用，用<code>&amp;&amp;</code>来获得右值引用，右值引用只能绑定到要销毁的对象。为了和右值引用区分开，常规的引用称为左值引用。</p>
<p>举例：</p>
 <figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;iostream&gt;</span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;vector&gt;</span></span></span><br><span class="line"><span class="keyword">using</span> <span class="keyword">namespace</span> std;</span><br><span class="line"><span class="function"><span class="keyword">int</span> <span class="title">main</span><span class="params">()</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">    <span class="keyword">int</span> var = <span class="number">42</span>;</span><br><span class="line">    <span class="keyword">int</span> &amp;l_var = var;</span><br><span class="line">    <span class="keyword">int</span> &amp;&amp;r_var = var; <span class="comment">// error: cannot bind rvalue reference of type &#x27;int&amp;&amp;&#x27; to lvalue of type &#x27;int&#x27; 错误：不能将右值引用绑定到左值上</span></span><br><span class="line"></span><br><span class="line">    <span class="keyword">int</span> &amp;&amp;r_var2 = var + <span class="number">40</span>; <span class="comment">// 正确：将 r_var2 绑定到求和结果上</span></span><br><span class="line">    <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
</li>
<li>
<p>标准库<code>move()</code>函数</p>
<p><code>move()</code> 函数：通过该函数可获得绑定到左值上的右值引用，该函数包括在 utility 头文件中。该知识点后序的章节中做详细的说明。</p>
</li>
<li>
<p>智能指针</p>
<p>相关知识已经在第一节中进行了详细的说明。</p>
</li>
<li>
<p><code>delete</code>函数和<code>default</code>函数</p>
<ul>
<li><code>delete</code>函数： <code>=delete</code> 表示该函数不能被调用。</li>
<li><code>default</code>函数：<code>=default</code>表示编译器生成默认的函数，例如：生成默认的构造函数。</li>
</ul>
 <figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;iostream&gt;</span></span></span><br><span class="line"><span class="keyword">using</span> <span class="keyword">namespace</span> std;</span><br><span class="line"></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">A</span></span></span><br><span class="line"><span class="class">&#123;</span></span><br><span class="line"><span class="keyword">public</span>:</span><br><span class="line">	<span class="built_in">A</span>() = <span class="keyword">default</span>; <span class="comment">// 表示使用默认的构造函数</span></span><br><span class="line">	~<span class="built_in">A</span>() = <span class="keyword">default</span>;	<span class="comment">// 表示使用默认的析构函数</span></span><br><span class="line">	<span class="built_in">A</span>(<span class="keyword">const</span> A &amp;) = <span class="keyword">delete</span>; <span class="comment">// 表示类的对象禁止拷贝构造</span></span><br><span class="line">	A &amp;<span class="keyword">operator</span>=(<span class="keyword">const</span> A &amp;) = <span class="keyword">delete</span>; <span class="comment">// 表示类的对象禁止拷贝赋值</span></span><br><span class="line">&#125;;</span><br><span class="line"><span class="function"><span class="keyword">int</span> <span class="title">main</span><span class="params">()</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">	A ex1;</span><br><span class="line">	A ex2 = ex1; <span class="comment">// error: use of deleted function &#x27;A::A(const A&amp;)&#x27;</span></span><br><span class="line">	A ex3;</span><br><span class="line">	ex3 = ex1; <span class="comment">// error: use of deleted function &#x27;A&amp; A::operator=(const A&amp;)&#x27;</span></span><br><span class="line">	<span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
</li>
</ol>
<h2 id="2-c和c的区别"><a class="markdownIt-Anchor" href="#2-c和c的区别"></a> 2、C和C++的区别</h2>
<p>面试高频指数：三星</p>
<hr>
<p>首先说一下面向对象和面向过程：</p>
<ul>
<li>面向过程的思路：分析解决问题所需的步骤，用函数把这些步骤依次实现。</li>
<li>面向对象的思路：把构成问题的事务分解为各个对象，建立对象的目的，不是完成一个步骤，而是描述某个事务在解决整个问题步骤中的行为。</li>
</ul>
<p>区别和联系：</p>
<ul>
<li>语言自身：C 语言是面向过程的编程，它最重要的特点是函数，通过 <code>main</code> 函数来调用各个子函数。程序运行的顺序都是程序员事先决定好的。C++ 是面向对象的编程，类是它的主要特点，在程序执行过程中，先由主 <code>main</code> 函数进入，定义一些类，根据需要执行类的成员函数，过程的概念被淡化了（实际上过程还是有的，就是主函数的那些语句。），以类驱动程序运行，类就是对象，所以我们称之为面向对象程序设计。面向对象在分析和解决问题的时候，将涉及到的数据和数据的操作封装在类中，通过类可以创建对象，以事件或消息来驱动对象执行处理。</li>
<li>应用领域：C 语言主要用于嵌入式领域，驱动开发等于硬件直接打交道的领域，C++ 可以用于应用层开发，用户界面开发等与操作系统打交道的领域。</li>
<li>C++ 既继承了 C 强大的底层操作特性，又被赋予了面向对象机制。它特性繁多，面向对象语言的多继承，对值传递与引用传递的区分以及 <code>const</code> 关键字，等等。</li>
<li>C++ 对 C 的“增强”，表现在以下几个方面：类型检查更为严格。增加了面向对象的机制、泛型编程的机制（Template）、异常处理、运算符重载、标准模板库（STL)、命名空间（避免全局命名冲突）。</li>
</ul>
<h2 id="3-java和c的区别"><a class="markdownIt-Anchor" href="#3-java和c的区别"></a> 3、Java和C++的区别</h2>
<p>面试高频指数：三星</p>
<hr>
<p>二者在语言特性上有很大的区别：</p>
<ul>
<li>指针：C++可以直接操作指针，容易产生内存泄漏以及非法指针引用的问题；Java并不是没有指针，虚拟机（JVM）内部还是使用了指针，只是编程人员不能直接使用指针，不能通过指针来直接访问内存，并且Java 增加了内存管理机制。</li>
<li>多重继承：C++ 支持多重继承，允许多个父类派生一个类，虽然功能很强大，但是如果使用的不当会造成很多问题。例如：菱形继承；Java不支持多重继承，但允许一个类可以继承多个接口，可以实现 C++ 多重继承的功能，但又避免了多重继承带来的许多不便。</li>
<li>数据类型和类：Java是完全面向对象的语言，所有函数和变量必须是类的一部分。除了基本数据类型之外，其余的都作为类对象，包括数组。对象将数据和方法结合起来，把它们封装在类中，这样每个对象都可实现自己的特点和行为。而C++允许将函数和变量定义为全局的。</li>
</ul>
<p>垃圾回收：</p>
<ul>
<li>Java 语言一个显著的特点就是垃圾回收机制，编程人员无需考虑内存管理的问题，可以有效地防止内存泄漏，有效地使用空闲的内存。</li>
<li>Java所有的对象都是用 new 操作符建立在内存堆栈上，类似于 C++ 中的 new 操作符，但是当要释放该申请的内存空间时，Java 自动进行内存回收操作，C++ 需要程序员自己释放内存空间，并且 Java 中的内存回收是以线程的方式在后台运行的，利用空闲时间。</li>
</ul>
<p>应用场景：</p>
<ul>
<li>Java 运行在虚拟机上，和开发平台无关，C++ 直接编译成可执行文件，是否跨平台在于用到的编译器的特性是否有多平台的支持。</li>
<li>C++ 可以直接编译成可执行文件，运行效率比 Java 高。</li>
<li>Java 主要用来开发 Web 应用。</li>
<li>C++ 主要用在嵌入式开发、网络、并发编程的方面。</li>
</ul>
<h2 id="4-python和c的区别"><a class="markdownIt-Anchor" href="#4-python和c的区别"></a> 4、Python和C++的区别</h2>
<p>面试高频指数：三星</p>
<hr>
<p>区别：</p>
<ul>
<li>语言自身：Python 为脚本语言，解释执行，不需要经过编译；C++是一种需要编译后才能运行的语言，在特定的机器上编译后运行。</li>
<li>运行效率：C<ins>运行效率高，安全稳定。原因：Python 代码和 C</ins> 最终都会变成 CPU 指令来跑，但一般情况下，比如反转和合并两个字符串，Python 最终转换出来的 CPU 指令回避 C++ 多很多。首先，Python 中涉及的内容比 C<ins>多，经过了更多层，Python 中甚至连数字都是 object；其次，Python 是解释执行的，和物理机 CPU 之间多了解释器这层，而 C</ins> 是编译执行的，直接就是机器码，编译的时候编译器又可以进行一些优化。</li>
<li>开发效率：Python 开发效率高。原因：Python 一两句代码就能实现的功能，C++ 往往需要更多的代码才能实现。</li>
<li>书写格式和语法不同：Python 的语法格式不同于其 C++ 定义声明才能使用，而且极其灵活，完全面向更上层的开发者。</li>
</ul>
<h1 id="三-面向对象"><a class="markdownIt-Anchor" href="#三-面向对象"></a> 三、面向对象</h1>
<h2 id="1-什么是面向对象面向对象的三大特性"><a class="markdownIt-Anchor" href="#1-什么是面向对象面向对象的三大特性"></a> 1、什么是面向对象？面向对象的三大特性</h2>
<p>面试高频指数：五星</p>
<hr>
<p>面向对象：对象是指具体的某一个事务，这些事务的抽象就是类，类中包含数据（成员变量）和动作（成员方法）。</p>
<p>面向对象的三大特性：</p>
<ul>
<li>封装：将具体的实现过程和数据封装成一个函数，只能通过接口进行访问，降低耦合性。</li>
<li>继承：子类继承父类的特征和行为，子类有父类的非 <code>private</code> 方法或成员变量，子类可以对父类的方法进行重写，增强了类之间的耦合性，但是当父类中的额成员变量、成员函数或者类本身被 <code>final</code> 关键字修饰时，修饰的类不能被继承，修饰的成员不能重写或修改。</li>
<li>多态：多态就是不同继承类的对象，对同一消息做出不同的响应，基类的指针指向或绑定到派生类的对象，使得基类指针呈现不同的表现方式。</li>
</ul>
<h2 id="2-重载-重写-隐藏的区别"><a class="markdownIt-Anchor" href="#2-重载-重写-隐藏的区别"></a> 2、重载、重写、隐藏的区别</h2>
<p>面试高频指数：五星</p>
<hr>
<p>概念解释：</p>
<ul>
<li>
<p>重载：是指同一可访问区内被声明几个具有不同参数列（参数的类型、个数、顺序）的同名函数，根据参数列表确定调用哪个函数，重载不关心函数返回类型。</p>
  <figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">A</span></span></span><br><span class="line"><span class="class">&#123;</span></span><br><span class="line"><span class="keyword">public</span>:</span><br><span class="line">    <span class="function"><span class="keyword">void</span> <span class="title">fun</span><span class="params">(<span class="keyword">int</span> tmp)</span></span>;</span><br><span class="line">    <span class="function"><span class="keyword">void</span> <span class="title">fun</span><span class="params">(<span class="keyword">float</span> tmp)</span></span>;        <span class="comment">// 重载 参数类型不同（相对于上一个函数）</span></span><br><span class="line">    <span class="function"><span class="keyword">void</span> <span class="title">fun</span><span class="params">(<span class="keyword">int</span> tmp, <span class="keyword">float</span> tmp1)</span></span>; <span class="comment">// 重载 参数个数不同（相对于上一个函数）</span></span><br><span class="line">    <span class="function"><span class="keyword">void</span> <span class="title">fun</span><span class="params">(<span class="keyword">float</span> tmp, <span class="keyword">int</span> tmp1)</span></span>; <span class="comment">// 重载 参数顺序不同（相对于上一个函数）</span></span><br><span class="line">    <span class="function"><span class="keyword">int</span> <span class="title">fun</span><span class="params">(<span class="keyword">int</span> tmp)</span></span>;            <span class="comment">// error: &#x27;int A::fun(int)&#x27; cannot be overloaded 错误：注意重载不关心函数返回类型</span></span><br><span class="line">&#125;;</span><br></pre></td></tr></table></figure>
</li>
<li>
<p>隐藏：是指派生类的函数屏蔽了与其同名的基类函数，主要只要同名函数，不管参数列表是否相同，基类函数都会被隐藏。</p>
  <figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;iostream&gt;</span></span></span><br><span class="line"><span class="keyword">using</span> <span class="keyword">namespace</span> std;</span><br><span class="line"></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Base</span></span></span><br><span class="line"><span class="class">&#123;</span></span><br><span class="line"><span class="keyword">public</span>:</span><br><span class="line">    <span class="function"><span class="keyword">void</span> <span class="title">fun</span><span class="params">(<span class="keyword">int</span> tmp, <span class="keyword">float</span> tmp1)</span> </span>&#123; cout &lt;&lt; <span class="string">&quot;Base::fun(int tmp, float tmp1)&quot;</span> &lt;&lt; endl; &#125;</span><br><span class="line">&#125;;</span><br><span class="line"></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Derive</span> :</span> <span class="keyword">public</span> Base</span><br><span class="line">&#123;</span><br><span class="line"><span class="keyword">public</span>:</span><br><span class="line">    <span class="function"><span class="keyword">void</span> <span class="title">fun</span><span class="params">(<span class="keyword">int</span> tmp)</span> </span>&#123; cout &lt;&lt; <span class="string">&quot;Derive::fun(int tmp)&quot;</span> &lt;&lt; endl; &#125; <span class="comment">// 隐藏基类中的同名函数</span></span><br><span class="line">&#125;;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">int</span> <span class="title">main</span><span class="params">()</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">    Derive ex;</span><br><span class="line">    ex.<span class="built_in">fun</span>(<span class="number">1</span>);       <span class="comment">// Derive::fun(int tmp)</span></span><br><span class="line">    ex.<span class="built_in">fun</span>(<span class="number">1</span>, <span class="number">0.01</span>); <span class="comment">// error: candidate expects 1 argument, 2 provided</span></span><br><span class="line">    <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>说明：上述代码中 <code>ex.fun(1, 0.01);</code> 出现错误，说明派生类中将基类的同名函数隐藏了。若是想调用基类中的同名函数，可以加上类型名指明 <code>ex.Base::fun(1, 0.01);</code>，这样就可以调用基类中的同名函数。</p>
</li>
<li>
<p>重写（覆盖）：是指派生类中存在重新定义的函数。函数名、参数列表、返回值类型都必须同基类中被重写的函数一致，只有函数体不同。派生类调用时会调用派生类的重写函数，不会调用被重写函数。重写的基类中被重写的函数必须有 <code>virtual</code> 修饰。</p>
  <figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;iostream&gt;</span></span></span><br><span class="line"><span class="keyword">using</span> <span class="keyword">namespace</span> std;</span><br><span class="line"></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Base</span></span></span><br><span class="line"><span class="class">&#123;</span></span><br><span class="line"><span class="keyword">public</span>:</span><br><span class="line">    <span class="function"><span class="keyword">virtual</span> <span class="keyword">void</span> <span class="title">fun</span><span class="params">(<span class="keyword">int</span> tmp)</span> </span>&#123; cout &lt;&lt; <span class="string">&quot;Base::fun(int tmp) : &quot;</span> &lt;&lt; tmp &lt;&lt; endl; &#125;</span><br><span class="line">&#125;;</span><br><span class="line"></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Derived</span> :</span> <span class="keyword">public</span> Base</span><br><span class="line">&#123;</span><br><span class="line"><span class="keyword">public</span>:</span><br><span class="line">    <span class="function"><span class="keyword">virtual</span> <span class="keyword">void</span> <span class="title">fun</span><span class="params">(<span class="keyword">int</span> tmp)</span> </span>&#123; cout &lt;&lt; <span class="string">&quot;Derived::fun(int tmp) : &quot;</span> &lt;&lt; tmp &lt;&lt; endl; &#125; <span class="comment">// 重写基类中的 fun 函数</span></span><br><span class="line">&#125;;</span><br><span class="line"><span class="function"><span class="keyword">int</span> <span class="title">main</span><span class="params">()</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">    Base *p = <span class="keyword">new</span> <span class="built_in">Derived</span>();</span><br><span class="line">    p-&gt;<span class="built_in">fun</span>(<span class="number">3</span>); <span class="comment">// Derived::fun(int) : 3</span></span><br><span class="line">    <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
</li>
</ul>
<p><strong>重写和重载的区别</strong></p>
<ul>
<li>范围区别：对于类中函数的重载或者重写而言，重载发生在同一个类的内部，重写发生在不同的类之间（子类和父类之间）。</li>
<li>参数区别：重载的函数需要与原函数有相同的函数名、不同的参数列表，不关注函数的返回值类型；重写的函数的函数名、参数列表和返回值类型都需要和原函数相同，父类中被重写的函数需要有 <code>virtual</code> 修饰。</li>
<li><code>virtual</code> 关键字：重写的函数基类中必须有 <code>virtual</code> 关键字的修饰，重载的函数可以有 <code>virtual</code> 关键字的修饰也可以没有。</li>
</ul>
<p><strong>隐藏和重写、重载的区别</strong></p>
<ul>
<li>范围区别：隐藏与重载范围不同，隐藏发生在不同类中。</li>
<li>参数区别：隐藏函数和被隐藏函数参数列表可以相同，也可以不同，但函数名一定相同；当参数不同时，无论基类中的函数是否被 <code>virtual</code> 修饰，基类函数都是被隐藏，而不是重写。</li>
</ul>
<h2 id="3-如何理解-c-是面向对象编程"><a class="markdownIt-Anchor" href="#3-如何理解-c-是面向对象编程"></a> 3、如何理解 C++ 是面向对象编程</h2>
<p>面试高频指数：三星</p>
<hr>
<p>说明：最好结合自己的项目经历进行展开解释，或举一些恰当的例自，同时对比下面向过程编程。</p>
<ul>
<li><strong>面向过程编程</strong>：一种以执行程序操作的郭恒或函数为中心编写软件的方法。程序的数据通常存储在变量中，与这些过程是分开的。所以必须将变量传递给需要使用它们的函数。缺点：随着程序变得越来越复杂，程序数据与运行代码的分离可能会导致问题。例如，程序的规范经常会发生变化，从而需要更改数据的格式或数据结构的设计。当数据结构发生变化时，对数据进行操作的代码也必须更改为接受新的格式。查找需要更改的所有代码会为程序员带来额外的工作，并增加了使代码出现错误的机会。</li>
<li><strong>面向对象编程（Object-Oriented Programming，OOP）</strong>：以创建和使用对象为中心。一个对象（Object）就是一个软件实体，它将数据和程序在一个单元中组合起来。对象的数据项，也称为其属性，存储在成员变量中。对象执行的过程被称为其成员函数。将对象的数据和过程绑定在一起则被称为封装。</li>
</ul>
<p><strong>面向对象编程进一步说明：</strong></p>
<p>面向对象编程将数据成员和成员函数封装到一个类中，并声明数据成员和成员函数的访问级别（<code>public</code>、<code>private</code>、<code>protected</code>），以便控制类对象对数据成员和函数的访问，对数据成员起到一定的保护作用。而且在类的对象调用成员函数时，只需知道成员函数的名、参数列表以及返回值类型即可，无需了解其函数的实现原理。当类内部的数据成员或者成员函数发生改变时，不影响类外部的代码。</p>
<h2 id="4-什么是多态多态如何实现"><a class="markdownIt-Anchor" href="#4-什么是多态多态如何实现"></a> 4、什么是多态？多态如何实现？</h2>
<p>面试高频指数：五星</p>
<hr>
<p><strong>多态：</strong> 堕胎就是不同继承类的对象，对同一消息做出不同的响应，基类的指针指向或绑定到派生类的对象，使得基类指针呈现不同的表现方式。在基类的函数前加上 <code>virtual</code> 关键字，在派生类中重写该函数，运行时将会根据对象的实际类型来调用相应的函数。如果对象类型是派生类，就调用派生类的函数；如果对象类型是基类，就调用基类的函数。</p>
<p><strong>实现方法：</strong> 多态是通过虚函数实现的，虚函数的地址保存在虚函数表中，虚函数表的地址保存在含有虚函数的类的实例对象的内存空间中。</p>
<p><strong>实现过程：</strong></p>
<ol>
<li>在类中用 <code>virtual</code> 关键字声明的函数叫做虚函数；</li>
<li>存在虚函数的类都有一个虚函数表，当创建一个该类的对象时，该对象有一个指向虚函数表的虚表指针（虚函数表和类对应的，虚表指针是和对象对应）；</li>
<li>当基类指针指向派生类对象，基类指针调用虚函数时，基类指针指向派生类的虚表指针，由于该虚表指针指向派生类的虚函数表，通过遍历虚表，寻找相同的虚函数。</li>
</ol>
<p>举例：</p>
<figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;iostream&gt;</span></span></span><br><span class="line"><span class="keyword">using</span> <span class="keyword">namespace</span> std;</span><br><span class="line"></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Base</span></span></span><br><span class="line"><span class="class">&#123;</span></span><br><span class="line"><span class="keyword">public</span>:</span><br><span class="line">	<span class="function"><span class="keyword">virtual</span> <span class="keyword">void</span> <span class="title">fun</span><span class="params">()</span> </span>&#123; cout &lt;&lt; <span class="string">&quot;Base::fun()&quot;</span> &lt;&lt; endl; &#125;</span><br><span class="line"></span><br><span class="line">	<span class="function"><span class="keyword">virtual</span> <span class="keyword">void</span> <span class="title">fun1</span><span class="params">()</span> </span>&#123; cout &lt;&lt; <span class="string">&quot;Base::fun1()&quot;</span> &lt;&lt; endl; &#125;</span><br><span class="line"></span><br><span class="line">	<span class="function"><span class="keyword">virtual</span> <span class="keyword">void</span> <span class="title">fun2</span><span class="params">()</span> </span>&#123; cout &lt;&lt; <span class="string">&quot;Base::fun2()&quot;</span> &lt;&lt; endl; &#125;</span><br><span class="line">&#125;;</span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Derive</span> :</span> <span class="keyword">public</span> Base</span><br><span class="line">&#123;</span><br><span class="line"><span class="keyword">public</span>:</span><br><span class="line">	<span class="function"><span class="keyword">void</span> <span class="title">fun</span><span class="params">()</span> </span>&#123; cout &lt;&lt; <span class="string">&quot;Derive::fun()&quot;</span> &lt;&lt; endl; &#125;</span><br><span class="line"></span><br><span class="line">	<span class="function"><span class="keyword">virtual</span> <span class="keyword">void</span> <span class="title">D_fun1</span><span class="params">()</span> </span>&#123; cout &lt;&lt; <span class="string">&quot;Derive::D_fun1()&quot;</span> &lt;&lt; endl; &#125;</span><br><span class="line"></span><br><span class="line">	<span class="function"><span class="keyword">virtual</span> <span class="keyword">void</span> <span class="title">D_fun2</span><span class="params">()</span> </span>&#123; cout &lt;&lt; <span class="string">&quot;Derive::D_fun2()&quot;</span> &lt;&lt; endl; &#125;</span><br><span class="line">&#125;;</span><br><span class="line"><span class="function"><span class="keyword">int</span> <span class="title">main</span><span class="params">()</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">	Base *p = <span class="keyword">new</span> <span class="built_in">Derive</span>();</span><br><span class="line">	p-&gt;<span class="built_in">fun</span>(); <span class="comment">// Derive::fun() 调用派生类中的虚函数</span></span><br><span class="line">	<span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>基类的虚函数表如下：</p>
<p><img src="https://gitee.com/maureen-liu/typora-image/raw/master/typora-image/1612675767-guREBN-image.png" alt="image.png"></p>
<p>派生类的对象虚函数表如下：</p>
<p><img src="https://gitee.com/maureen-liu/typora-image/raw/master/typora-image/1618818155-PZxTzJ-image.png" alt="image.png"></p>
<p>简单解释：当基类的指针指向派生类的对象时，通过派生类的对象的虚表指针找到虚函数表（派生类的对象虚函数表）进而找到相应的虚函数 <code>Derive::f()</code> 进行调用。</p>
<h1 id="四-关键字库函数"><a class="markdownIt-Anchor" href="#四-关键字库函数"></a> 四、关键字库函数</h1>
<h2 id="1-sizeof-和-strlen-的区别"><a class="markdownIt-Anchor" href="#1-sizeof-和-strlen-的区别"></a> 1、sizeof 和 strlen 的区别</h2>
<p>面试高频指数：三星</p>
<hr>
<ol>
<li>
<p><code>strlen</code> 是头文件 <code>&lt;cstring&gt;</code>中的函数，<code>sizeof</code> 是 C++ 中的运算符。</p>
</li>
<li>
<p><code>strlen</code> 测量的是字符串的实际长度（其源代码如下），以 <code>\0</code> 结束。而 <code>sizeof</code> 测量的是字符数组的分配大小。</p>
<p><code>strlen</code> 源代码：</p>
 <figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">size_t</span> <span class="title">strlen</span><span class="params">(<span class="keyword">const</span> <span class="keyword">char</span> *str)</span> </span>&#123;</span><br><span class="line">    <span class="keyword">size_t</span> length = <span class="number">0</span>;</span><br><span class="line">    <span class="keyword">while</span> (*str++)</span><br><span class="line">        ++length;</span><br><span class="line">    <span class="keyword">return</span> length;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>举例：</p>
 <figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;iostream&gt;</span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;cstring&gt;</span></span></span><br><span class="line"></span><br><span class="line"><span class="keyword">using</span> <span class="keyword">namespace</span> std;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">int</span> <span class="title">main</span><span class="params">()</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">    <span class="keyword">char</span> arr[<span class="number">10</span>] = <span class="string">&quot;hello&quot;</span>;</span><br><span class="line">    cout &lt;&lt; <span class="built_in">strlen</span>(arr) &lt;&lt; endl; <span class="comment">// 5</span></span><br><span class="line">    cout &lt;&lt; <span class="built_in"><span class="keyword">sizeof</span></span>(arr) &lt;&lt; endl; <span class="comment">// 10</span></span><br><span class="line">    <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
</li>
<li>
<p>若字符数组 arr 作为函数的形参，<code>sizeof(arr)</code> 中 arr 被当作字符指针来处理，<code>strlen(arr)</code> 中 arr 依然是字符数组，从下述程序的运行结果中就可以看出。</p>
 <figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;iostream&gt;</span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;cstring&gt;</span></span></span><br><span class="line"></span><br><span class="line"><span class="keyword">using</span> <span class="keyword">namespace</span> std;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">void</span> <span class="title">size_of</span><span class="params">(<span class="keyword">char</span> arr[])</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">    cout &lt;&lt; <span class="built_in"><span class="keyword">sizeof</span></span>(arr) &lt;&lt; endl; <span class="comment">// warning: &#x27;sizeof&#x27; on array function parameter &#x27;arr&#x27; will return size of &#x27;char*&#x27; .</span></span><br><span class="line">    cout &lt;&lt; <span class="built_in">strlen</span>(arr) &lt;&lt; endl; </span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">int</span> <span class="title">main</span><span class="params">()</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">    <span class="keyword">char</span> arr[<span class="number">20</span>] = <span class="string">&quot;hello&quot;</span>;</span><br><span class="line">    <span class="built_in">size_of</span>(arr); </span><br><span class="line">    <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">&#125;</span><br><span class="line"><span class="comment">/*</span></span><br><span class="line"><span class="comment">输出结果：</span></span><br><span class="line"><span class="comment">8</span></span><br><span class="line"><span class="comment">5</span></span><br><span class="line"><span class="comment">*/</span></span><br></pre></td></tr></table></figure>
</li>
<li>
<p><code>strlen</code> 本身是库函数，因此在程序运行过程中，计算长度；而 <code>sizeof</code> 在编译时，计算长度。</p>
</li>
<li>
<p><code>sizeof</code> 的参数可以是类型，也可以是变量；<code>strlen</code> 的参数必须是 <code>char *</code> 类型的变量。</p>
</li>
</ol>
<h2 id="2-lambda-表达式匿名函数的具体应用和使用场景"><a class="markdownIt-Anchor" href="#2-lambda-表达式匿名函数的具体应用和使用场景"></a> 2、lambda 表达式（匿名函数）的具体应用和使用场景</h2>
<p>面试高频指数：三星</p>
<hr>
<p><code>lambda</code> 表达式的定义形式如下：</p>
<figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">[capture list] (parameter list) -&gt; reurn type</span><br><span class="line">&#123;</span><br><span class="line">   function body</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>其中：</p>
<ul>
<li>capature list：捕获列表，指 lambda 表达式所在函数中定义的局部变量的列表，通常为空，但如果函数体中用到了 lambda 表达式所在函数的局部变量，必须捕获该变量，即将此变量写在捕获列表中。捕获方式分为：引用捕获方式<code>[&amp;]</code>、值捕获方式<code>[=]</code>。</li>
<li>return type、parameter list、function body：分别表示返回值类型、参数类型、函数体，和普通函数一样。</li>
</ul>
<p>举例：</p>
<p>lambda 表达式常搭配排序算法使用。</p>
<figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;iostream&gt;</span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;vector&gt;</span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;algorithm&gt;</span></span></span><br><span class="line"><span class="keyword">using</span> <span class="keyword">namespace</span> std;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">int</span> <span class="title">main</span><span class="params">()</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">    vector&lt;<span class="keyword">int</span>&gt; arr = &#123;<span class="number">3</span>, <span class="number">4</span>, <span class="number">76</span>, <span class="number">12</span>, <span class="number">54</span>, <span class="number">90</span>, <span class="number">34</span>&#125;;</span><br><span class="line">    <span class="built_in">sort</span>(arr.<span class="built_in">begin</span>(), arr.<span class="built_in">end</span>(), [](<span class="keyword">int</span> a, <span class="keyword">int</span> b) &#123; <span class="keyword">return</span> a &gt; b; &#125;); <span class="comment">// 降序排序</span></span><br><span class="line">    <span class="keyword">for</span> (<span class="keyword">auto</span> a : arr)</span><br><span class="line">    &#123;</span><br><span class="line">        cout &lt;&lt; a &lt;&lt; <span class="string">&quot; &quot;</span>;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">&#125;</span><br><span class="line"><span class="comment">/*</span></span><br><span class="line"><span class="comment">运行结果：90 76 54 34 12 4 3</span></span><br><span class="line"><span class="comment">*/</span></span><br></pre></td></tr></table></figure>
<h2 id="3-explicit-的作用如何避免编译器进行隐式类型转换"><a class="markdownIt-Anchor" href="#3-explicit-的作用如何避免编译器进行隐式类型转换"></a> 3、explicit 的作用（如何避免编译器进行隐式类型转换）</h2>
<p>面试高频指数：三星</p>
<hr>
<p>作用：用来声明类构造函数是显式调用的，而非隐式调用，可以阻止调用构造函数时进行隐式转换。只可用于修饰单参构造函数，因为无参构造函数和多参构造函数本身就是显式调用的，再加上 <code>explicit</code> 关键字也没有什么意义。</p>
<p>隐式转换：</p>
<figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;iostream&gt;</span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;cstring&gt;</span></span></span><br><span class="line"><span class="keyword">using</span> <span class="keyword">namespace</span> std;</span><br><span class="line"></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">A</span></span></span><br><span class="line"><span class="class">&#123;</span></span><br><span class="line"><span class="keyword">public</span>:</span><br><span class="line">    <span class="keyword">int</span> var;</span><br><span class="line">    <span class="built_in">A</span>(<span class="keyword">int</span> tmp)</span><br><span class="line">    &#123;</span><br><span class="line">        var = tmp;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;;</span><br><span class="line"><span class="function"><span class="keyword">int</span> <span class="title">main</span><span class="params">()</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">    A ex = <span class="number">10</span>; <span class="comment">// 发生了隐式转换</span></span><br><span class="line">    <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>上述代码中，<code>A ex = 10;</code> 在编译时，进行了隐式转换，将 <code>10</code> 转换成 <code>A</code> 类型的对象，然后将该对象赋值给 <code>ex</code>，等同于如下操作：</p>
<p>为了避免隐式转换，可用 <code>explicit</code> 关键字进行声明：</p>
<figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;iostream&gt;</span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;cstring&gt;</span></span></span><br><span class="line"><span class="keyword">using</span> <span class="keyword">namespace</span> std;</span><br><span class="line"></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">A</span></span></span><br><span class="line"><span class="class">&#123;</span></span><br><span class="line"><span class="keyword">public</span>:</span><br><span class="line">    <span class="keyword">int</span> var;</span><br><span class="line">    <span class="function"><span class="keyword">explicit</span> <span class="title">A</span><span class="params">(<span class="keyword">int</span> tmp)</span></span></span><br><span class="line"><span class="function">    </span>&#123;</span><br><span class="line">        var = tmp;</span><br><span class="line">        cout &lt;&lt; var &lt;&lt; endl;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;;</span><br><span class="line"><span class="function"><span class="keyword">int</span> <span class="title">main</span><span class="params">()</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">    <span class="function">A <span class="title">ex</span><span class="params">(<span class="number">100</span>)</span></span>;</span><br><span class="line">    A ex1 = <span class="number">10</span>; <span class="comment">// error: conversion from &#x27;int&#x27; to non-scalar type &#x27;A&#x27; requested</span></span><br><span class="line">    <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<h2 id="4-c-和-c-static的区别"><a class="markdownIt-Anchor" href="#4-c-和-c-static的区别"></a> 4、C 和 C++ static的区别</h2>
<p>面试高频指数：1星</p>
<hr>
<ul>
<li>在 C 语言中，使用 <code>static</code> 可以定义局部静态变量、外部静态变量、静态函数</li>
<li>在 C++ 中，使用 <code>static</code> 可以定义局部静态变量、外部静态变量、静态函数、静态成员变量和静态成员函数。因为 C++ 中有类的概念，静态成员变量、静态成员函数都是与类有关的概念。</li>
</ul>
<h2 id="5-static-的作用"><a class="markdownIt-Anchor" href="#5-static-的作用"></a> 5、static 的作用</h2>
<p>面试高频指数：四星</p>
<hr>
<p>作用：</p>
<p><code>static</code> 定义静态变量，静态函数。</p>
<ul>
<li>
<p>保持变量内容持久性：<code>static</code> 作用于局部变量，改变了局部变量的生存周期，使得该变量存在于定义后直到程序运行结束的这段时间。</p>
  <figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;iostream&gt;</span></span></span><br><span class="line"><span class="keyword">using</span> <span class="keyword">namespace</span> std;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">int</span> <span class="title">fun</span><span class="params">()</span></span>&#123;</span><br><span class="line">    <span class="keyword">static</span> <span class="keyword">int</span> var = <span class="number">1</span>; <span class="comment">// var 只在第一次进入这个函数的时初始化</span></span><br><span class="line">    var += <span class="number">1</span>;</span><br><span class="line">    <span class="keyword">return</span> var;</span><br><span class="line">&#125;</span><br><span class="line">  </span><br><span class="line"><span class="function"><span class="keyword">int</span> <span class="title">main</span><span class="params">()</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">    <span class="keyword">for</span>(<span class="keyword">int</span> i = <span class="number">0</span>; i &lt; <span class="number">10</span>; ++i)</span><br><span class="line">    	cout &lt;&lt; <span class="built_in">fun</span>() &lt;&lt; <span class="string">&quot; &quot;</span>; <span class="comment">// 2 3 4 5 6 7 8 9 10 11</span></span><br><span class="line">    <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
</li>
<li>
<p>隐藏：<code>static</code> 作用于全局变量和函数，改变了全局变量和函数的作用域，使得全局变量和函数只能在定义它的文件中使用，在源文件中不具有全局可见性。（注：普通全局变量和函数具有全局可见性，即其它的源文件也可以使用。）</p>
</li>
<li>
<p><code>static</code> 作用于类的成员变量和类的成员函数，使得类变量或者类成员函数和类有关，也就是说可以不定义类的对象就可以通过类访问这些静态成员。注意：类的静态成员函数中只能访问静态成员变量或者静态成员函数，不能将静态成员函数定义成虚函数。</p>
  <figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="meta-keyword">include</span><span class="meta-string">&lt;iostream&gt;</span></span></span><br><span class="line"><span class="keyword">using</span> <span class="keyword">namespace</span> std;</span><br><span class="line"></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">A</span></span></span><br><span class="line"><span class="class">&#123;</span></span><br><span class="line"><span class="keyword">private</span>:</span><br><span class="line">    <span class="keyword">int</span> var;</span><br><span class="line">    <span class="keyword">static</span> <span class="keyword">int</span> s_var; <span class="comment">// 静态成员变量</span></span><br><span class="line"><span class="keyword">public</span>:</span><br><span class="line">    <span class="function"><span class="keyword">void</span> <span class="title">show</span><span class="params">()</span></span></span><br><span class="line"><span class="function">    </span>&#123;</span><br><span class="line">        cout &lt;&lt; s_var++ &lt;&lt; endl;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="function"><span class="keyword">static</span> <span class="keyword">void</span> <span class="title">s_show</span><span class="params">()</span></span></span><br><span class="line"><span class="function">    </span>&#123;</span><br><span class="line">        cout &lt;&lt; s_var &lt;&lt; endl;</span><br><span class="line">		<span class="comment">// cout &lt;&lt; var &lt;&lt; endl; // error: invalid use of member &#x27;A::a&#x27; in static member function. 静态成员函数不能调用非静态成员变量。无法使用 this.var</span></span><br><span class="line">        <span class="comment">// show();  // error: cannot call member function &#x27;void A::show()&#x27; without object. 静态成员函数不能调用非静态成员函数。无法使用 this.show()</span></span><br><span class="line">    &#125;</span><br><span class="line">&#125;;</span><br><span class="line"><span class="keyword">int</span> A::s_var = <span class="number">1</span>;  <span class="comment">// 静态成员变量在类外进行初始化赋值，默认初始化为 0</span></span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">int</span> <span class="title">main</span><span class="params">()</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">    </span><br><span class="line">    <span class="comment">// cout &lt;&lt; A::sa &lt;&lt; endl;    // error: &#x27;int A::sa&#x27; is private within this context</span></span><br><span class="line">    A ex;</span><br><span class="line">    ex.<span class="built_in">show</span>();</span><br><span class="line">    A::<span class="built_in">s_show</span>();</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
</li>
</ul>
<h2 id="6-static-在类中使用的注意事项定义-初始化和使用"><a class="markdownIt-Anchor" href="#6-static-在类中使用的注意事项定义-初始化和使用"></a> 6、static 在类中使用的注意事项（定义、初始化和使用）</h2>
<p>面试高频指数：五星</p>
<hr>
<p><strong>static静态成员变量：</strong></p>
<ol>
<li>
<p>静态成员变量是在类内进行声明，在类外进行定义和初始化，在类外进行定义和初始化的时候不要出现 <code>static</code> 关键字和 <code>private</code>、<code>public</code>、<code>protected</code> 访问规则。</p>
</li>
<li>
<p>静态成员变量相当于类域中的全局变量，被类的所有对象所共享，包括派生类的对象。</p>
</li>
<li>
<p>静态成员变量可以作为成员函数的参数，而普通成员变量不可以。</p>
 <figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;iostream&gt;</span></span></span><br><span class="line"><span class="keyword">using</span> <span class="keyword">namespace</span> std;</span><br><span class="line"></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">A</span></span></span><br><span class="line"><span class="class">&#123;</span></span><br><span class="line"><span class="keyword">public</span>:</span><br><span class="line">    <span class="keyword">static</span> <span class="keyword">int</span> s_var;</span><br><span class="line">    <span class="keyword">int</span> var;</span><br><span class="line">    <span class="function"><span class="keyword">void</span> <span class="title">fun1</span><span class="params">(<span class="keyword">int</span> i = s_var)</span></span>; <span class="comment">// 正确，静态成员变量可以作为成员函数的参数</span></span><br><span class="line">    <span class="function"><span class="keyword">void</span> <span class="title">fun2</span><span class="params">(<span class="keyword">int</span> i = var)</span></span>;   <span class="comment">//  error: invalid use of non-static data member &#x27;A::var&#x27;</span></span><br><span class="line">&#125;;</span><br><span class="line"><span class="function"><span class="keyword">int</span> <span class="title">main</span><span class="params">()</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">    <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
</li>
<li>
<p>静态数据成员的类型可以是所属类的类型，而普通数据成员的类型只能是该类类型的指针或引用。</p>
 <figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;iostream&gt;</span></span></span><br><span class="line"><span class="keyword">using</span> <span class="keyword">namespace</span> std;</span><br><span class="line"></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">A</span></span></span><br><span class="line"><span class="class">&#123;</span></span><br><span class="line"><span class="keyword">public</span>:</span><br><span class="line">    <span class="keyword">static</span> A s_var; <span class="comment">// 正确，静态数据成员</span></span><br><span class="line">    A var;          <span class="comment">// error: field &#x27;var&#x27; has incomplete type &#x27;A&#x27;</span></span><br><span class="line">    A *p;           <span class="comment">// 正确，指针</span></span><br><span class="line">    A &amp;var1;        <span class="comment">// 正确，引用</span></span><br><span class="line">&#125;;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">int</span> <span class="title">main</span><span class="params">()</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">    <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
</li>
</ol>
<p><strong>static 静态成员函数：</strong></p>
<ol>
<li>静态成员函数不能调用非静态成员变量或者非静态成员函数，因为静态成员函数没有  <code>this</code> 指针。静态成员函数作为类作用域的全局函数。</li>
<li>静态成员函数不能声明成虚函数（<code>virtual</code>)、<code>const</code>函数和 <code>volatile</code> 函数。</li>
</ol>
<h2 id="7-static-全局变量和普通全局变量的异同"><a class="markdownIt-Anchor" href="#7-static-全局变量和普通全局变量的异同"></a> 7、static 全局变量和普通全局变量的异同</h2>
<p>面试高频指数：三星</p>
<hr>
<p>相同点：</p>
<ul>
<li>存储方式：普通全局变量和 <code>static</code> 全局变量都是静态存储方式。</li>
</ul>
<p>不同点：</p>
<ul>
<li>作用域：普通全局变量的作用域是整个源程序，当一个源程序由多个源文件组成时，普通全局变量在各个源文件中都是有效的；静态全局变量则限制了其作用域，即只在定义该变量的源文件内有效，在同一源程序的其他源文件中不能使用它。由于静态全局变量的作用域限于一个源文件内，只能为该源文件内的函数共用，因此可以避免在其他源文件中引起错误。</li>
<li>初始化：静态全局变量只初始化一次，防止在其他文件中使用。</li>
</ul>
<h2 id="8-const-作用及用法"><a class="markdownIt-Anchor" href="#8-const-作用及用法"></a> 8、const 作用及用法</h2>
<p>面试高频指数：三星</p>
<hr>
<p>作用：</p>
<ul>
<li><code>const</code> 修饰成员变量，定义成 <code>const</code> 常量，相较于宏常量，可以进行类型检查，节省内存空间，提高了效率。</li>
<li><code>const</code> 修饰函数参数，使得传递过来的函数参数的值不能改变。</li>
<li><code>const</code> 修饰成员函数，使得成员函数不能修改任何类型的成员变量（<code>mutable</code> 修饰的变量除外），也不能调用非 <code>const</code> 成员函数，因为非 <code>const</code> 成员函数可能会修改成员变量。</li>
</ul>
<p>在类中的用法：</p>
<p><code>const</code> 成员变量：</p>
<ol>
<li><code>const</code>成员变量只能在类内声明、定义，在构造函数初始化列表中初始化。</li>
<li><code>const</code> 成员变量只在某个对象的生命周期内是常量，对于整个类而言却是可变的，因为类可以创建多个对象，不同类的 <code>const</code> 成员变量的值是不同的。因此不能在类的声明中初始化 <code>const</code> 成员变量，类的对象还没有创建，编译器不知道它的值。</li>
</ol>
<p><code>const</code> 成员函数：</p>
<ol>
<li>不能修改成员变量的值，除非有 <code>mutable</code> 修饰；只能访问成员变量。</li>
<li>不能调用非常量成员函数，以防修改成员变量的值。</li>
</ol>
<figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;iostream&gt;</span></span></span><br><span class="line"><span class="keyword">using</span> <span class="keyword">namespace</span> std;</span><br><span class="line"></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">A</span></span></span><br><span class="line"><span class="class">&#123;</span></span><br><span class="line"><span class="keyword">public</span>:</span><br><span class="line">	<span class="keyword">int</span> var;</span><br><span class="line">	<span class="built_in">A</span>(<span class="keyword">int</span> tmp) : <span class="built_in">var</span>(tmp) &#123;&#125;</span><br><span class="line">	<span class="function"><span class="keyword">void</span> <span class="title">c_fun</span><span class="params">(<span class="keyword">int</span> tmp)</span> <span class="keyword">const</span> <span class="comment">// const 成员函数</span></span></span><br><span class="line"><span class="function">	</span>&#123;</span><br><span class="line">		var = tmp; <span class="comment">// error: assignment of member &#x27;A::var&#x27; in read-only object. 在 const 成员函数中，不能修改任何类成员变量。		</span></span><br><span class="line">		<span class="built_in">fun</span>(tmp); <span class="comment">// error: passing &#x27;const A&#x27; as &#x27;this&#x27; argument discards qualifiers. const 成员函数不能调用非 const 成员函数，因为非 const 成员函数可能会修改成员变量。</span></span><br><span class="line">	&#125;</span><br><span class="line"></span><br><span class="line">	<span class="function"><span class="keyword">void</span> <span class="title">fun</span><span class="params">(<span class="keyword">int</span> tmp)</span></span></span><br><span class="line"><span class="function">	</span>&#123;</span><br><span class="line">		var = tmp;</span><br><span class="line">	&#125;</span><br><span class="line">&#125;;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">int</span> <span class="title">main</span><span class="params">()</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">    <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<h2 id="9-define-和-const-的区别"><a class="markdownIt-Anchor" href="#9-define-和-const-的区别"></a> 9、define 和 const 的区别</h2>
<p>面试高频指数：三星</p>
<hr>
<p>区别：</p>
<ul>
<li>编译阶段：<code>define</code> 是在编译预处理阶段进行替换，<code>const</code> 是在编译阶段确定其值。</li>
<li>安全性：<code>define</code> 定义的宏常量没有数据类型，只是进行简单的替换，不会进行类型安全的检查；<code>const</code> 定义的常量时有类型的，是要进行判断的，可以避免一些低级错误。</li>
<li>内存占用：<code>define</code> 定义的宏常量，在程序中使用多少次就会进行多少次天幻，内存中有多个备份，占用的是代码段的空间；<code>const</code> 定义的常量占用的静态存储区的空间，程序运行过程中只有一份。</li>
<li>调试：<code>define</code> 定义的宏常量不能调试，因为在预编译阶段就已经进行替换了；<code>const</code>定义的常量可以进行调试。</li>
</ul>
<p><code>const</code> 的优点：</p>
<ul>
<li>有数据类型，在定义时可以进行安全性检查。</li>
<li>可调试。</li>
<li>占用较少的空间。</li>
</ul>
<h2 id="10-define-和-typedef-的区别"><a class="markdownIt-Anchor" href="#10-define-和-typedef-的区别"></a> 10、define 和 typedef 的区别</h2>
<p>面试高频指数：两星</p>
<hr>
<ul>
<li>原理：<code>#define</code> 作为预处理指令，在编译预处理时进行替换操作，不做正确性检查，只有在编译已被展开的源程序时才会发现可能的错误并报错。<code>typedef</code> 是关键字，在编译时处理，有类型检查功能，用来给一个已经存在的类型一个别名，但不能在一个函数定义里面使用 <code>typedef</code>。</li>
<li>功能：<code>typedef</code> 用来定义类型的别名，方便使用。<code>#define</code> 不仅可以为类型取别名，还可以定义常量、变量、编译开关等。</li>
<li>作用域：<code>#define</code> 没有作用域的限制，只要是之前预定义过的宏，在以后的程序中都可以使用，而<code>typedef</code> 有自己的作用域。</li>
<li>指针的操作：<code>typedef</code> 和 <code>#define</code> 在处理指针时不完全一样</li>
</ul>
<figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;iostream&gt;</span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">define</span> INTPTR1 int *</span></span><br><span class="line"><span class="keyword">typedef</span> <span class="keyword">int</span> * INTPTR2;</span><br><span class="line"></span><br><span class="line"><span class="keyword">using</span> <span class="keyword">namespace</span> std;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">int</span> <span class="title">main</span><span class="params">()</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">    INTPTR1 p1, p2; <span class="comment">// p1: int *; p2: int</span></span><br><span class="line">    INTPTR2 p3, p4; <span class="comment">// p3: int *; p4: int *</span></span><br><span class="line"></span><br><span class="line">    <span class="keyword">int</span> var = <span class="number">1</span>;</span><br><span class="line">    <span class="keyword">const</span> INTPTR1 p5 = &amp;var; <span class="comment">// 相当于 const int * p5; 常量指针，即不可以通过 p5 去修改 p5 指向的内容，但是 p5 可以指向其他内容。</span></span><br><span class="line">    <span class="keyword">const</span> INTPTR2 p6 = &amp;var; <span class="comment">// 相当于 int * const p6; 指针常量，不可使 p6 再指向其他内容。</span></span><br><span class="line">    </span><br><span class="line">    <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>注：对于指针常量和常量指针的区别，可查阅第6章。</p>
<h2 id="11-用宏实现比较大小以及两个数中的最小值"><a class="markdownIt-Anchor" href="#11-用宏实现比较大小以及两个数中的最小值"></a> 11、用宏实现比较大小，以及两个数中的最小值</h2>
<p>面试高频指数：1星</p>
<hr>
<p>具体代码如下：</p>
<figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;iostream&gt;</span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">define</span> MAX(X, Y) ((X)&gt;(Y)?(X):(Y))</span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">define</span> MIN(X, Y) ((X)&lt;(Y)?(X):(Y))</span></span><br><span class="line"><span class="keyword">using</span> <span class="keyword">namespace</span> std;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">int</span> <span class="title">main</span> <span class="params">()</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">    <span class="keyword">int</span> var1 = <span class="number">10</span>, var2 = <span class="number">100</span>;</span><br><span class="line">    cout &lt;&lt; <span class="built_in">MAX</span>(var1, var2) &lt;&lt; endl;</span><br><span class="line">    cout &lt;&lt; <span class="built_in">MIN</span>(var1, var2) &lt;&lt; endl;</span><br><span class="line">    <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">&#125;</span><br><span class="line"><span class="comment">/*</span></span><br><span class="line"><span class="comment">程序运行结果：</span></span><br><span class="line"><span class="comment">100</span></span><br><span class="line"><span class="comment">10</span></span><br><span class="line"><span class="comment">*/</span></span><br></pre></td></tr></table></figure>
<h2 id="12-inline-作用及使用方法"><a class="markdownIt-Anchor" href="#12-inline-作用及使用方法"></a> 12、inline 作用及使用方法</h2>
<p>面试高频指数：三星</p>
<hr>
<p>作用：</p>
<p><code>inline</code> 是一个关键字，可以用于定义内联函数。内联函数，就像普通函数一样被调用，但是在调用时并不通过函数调用的机制而是直接在调用点处展开，这样可以大大减少由函数调用带来的开销，从而提高程序的运行效率。</p>
<p>使用方法：</p>
<ol>
<li>
<p>类内定义成员函数默认是内联函数</p>
<p>在类内定义成员函数，可以不用在函数头部加 <code>inline</code> 关键字，因为编译器会自动将类内定义的函数（构造函数、析构函数、普通成员函数等）声明为内联函数，代码如下：</p>
 <figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;iostream&gt;</span></span></span><br><span class="line"><span class="keyword">using</span> <span class="keyword">namespace</span> std;</span><br><span class="line"></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">A</span>&#123;</span></span><br><span class="line"><span class="keyword">public</span>:</span><br><span class="line">    <span class="keyword">int</span> var;</span><br><span class="line">    <span class="built_in">A</span>(<span class="keyword">int</span> tmp)&#123; </span><br><span class="line">      var = tmp;</span><br><span class="line">    &#125;    </span><br><span class="line">    <span class="function"><span class="keyword">void</span> <span class="title">fun</span><span class="params">()</span></span>&#123; </span><br><span class="line">        cout &lt;&lt; var &lt;&lt; endl;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">int</span> <span class="title">main</span><span class="params">()</span></span></span><br><span class="line"><span class="function"></span>&#123;    </span><br><span class="line">    <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
</li>
<li>
<p>类外定义成员函数，若想定义为内联函数，需用关键字声明</p>
<p>当在类内声明函数，在类外定义函数时，如果想将该函数定义为内联函数，则可以在类内声明时不加<code>inline</code> 关键字，而在类外定义函数时加上 <code>inline</code> 关键字。</p>
 <figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;iostream&gt;</span></span></span><br><span class="line"><span class="keyword">using</span> <span class="keyword">namespace</span> std;</span><br><span class="line"></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">A</span>&#123;</span></span><br><span class="line"><span class="keyword">public</span>:</span><br><span class="line">    <span class="keyword">int</span> var;</span><br><span class="line">    <span class="built_in">A</span>(<span class="keyword">int</span> tmp)&#123; </span><br><span class="line">      var = tmp;</span><br><span class="line">    &#125;    </span><br><span class="line">    <span class="function"><span class="keyword">void</span> <span class="title">fun</span><span class="params">()</span></span>;</span><br><span class="line">&#125;;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">inline</span> <span class="keyword">void</span> <span class="title">A::fun</span><span class="params">()</span></span>&#123;</span><br><span class="line">    cout &lt;&lt; var &lt;&lt; endl;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">int</span> <span class="title">main</span><span class="params">()</span></span></span><br><span class="line"><span class="function"></span>&#123;    </span><br><span class="line">    <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>另外，可以在声明函数和定义函数的同时加上 <code>inline</code>；也可以只在函数声明时加 <code>inline</code>，而定义函数时不加 <code>inline</code>。只要确保在调用该函数之前把 <code>inline</code> 的信息告知编译器即可。</p>
</li>
</ol>
<h2 id="13-inline-函数工作原理"><a class="markdownIt-Anchor" href="#13-inline-函数工作原理"></a> 13、inline 函数工作原理</h2>
<p>面试高频指数：两星</p>
<hr>
<ul>
<li>内联函数不是在调用时发生控制转移关系，而是在编译阶段将函数体嵌入到每一个调用该函数的语句块中，编译器会将程序中出现内联函数的调用表达式用内联函数的函数体来替换。</li>
<li>普通函数是将程序执行转移到被调用函数所存放的内存地址，当函数执行完后，返回到执行此函数前的地方。转移操作需要保护现场，被调函数执行完后，再恢复现场，该过程需要较大的资源开销。</li>
</ul>
<h2 id="14-宏定义define和内联函数inline的区别"><a class="markdownIt-Anchor" href="#14-宏定义define和内联函数inline的区别"></a> 14、宏定义（define）和内联函数（inline）的区别</h2>
<p>面试高频指数：两星</p>
<hr>
<ol>
<li>内联函数是在编译时展开，而宏在编译预处理时展开；在编译的时候，内联函数直接被嵌入到目标代码中去，而宏只是一个简单的文本替换。</li>
<li>内联函数是真正的函数，和普通函数调用的方法一样，在调用点处直接展开，避免了函数的参数压栈操作，减少了调用的开销。而宏定义编写较为复杂，常需要增加一些括号来避免歧义。</li>
<li>宏定义只进行文本替换，不会对参数类型、语句能否正常编译等进行检查。而内联函数是真正的函数，会对参数的类型、函数体内的语句编写是否正确等进行检查。</li>
</ol>
<p>使用举例：</p>
<figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;iostream&gt;</span></span></span><br><span class="line"></span><br><span class="line"><span class="meta">#<span class="meta-keyword">define</span> MAX(a, b) ((a) &gt; (b) ? (a) : (b))</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">using</span> <span class="keyword">namespace</span> std;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">inline</span> <span class="keyword">int</span> <span class="title">fun_max</span><span class="params">(<span class="keyword">int</span> a, <span class="keyword">int</span> b)</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">    <span class="keyword">return</span> a &gt; b ? a : b;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">int</span> <span class="title">main</span><span class="params">()</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">    <span class="keyword">int</span> var = <span class="number">1</span>;</span><br><span class="line">    cout &lt;&lt; <span class="built_in">MAX</span>(var, <span class="number">5</span>) &lt;&lt; endl;     </span><br><span class="line">    cout &lt;&lt; <span class="built_in">fun_max</span>(var, <span class="number">0</span>) &lt;&lt; endl; </span><br><span class="line">    <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">&#125;</span><br><span class="line"><span class="comment">/*</span></span><br><span class="line"><span class="comment">程序运行结果：</span></span><br><span class="line"><span class="comment">5</span></span><br><span class="line"><span class="comment">1</span></span><br><span class="line"><span class="comment"></span></span><br><span class="line"><span class="comment">*/</span></span><br></pre></td></tr></table></figure>
<h2 id="15-new-的作用"><a class="markdownIt-Anchor" href="#15-new-的作用"></a> 15、new 的作用？</h2>
<p>面试高频指数：两星</p>
<hr>
<p><code>new</code> 是 C++ 中的关键字，用来动态分配内存空间，实现方式如下：</p>
<figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">int</span> *p = <span class="keyword">new</span> <span class="keyword">int</span>[<span class="number">5</span>];</span><br></pre></td></tr></table></figure>
<h2 id="16-new-和-malloc-如何判断是否申请到内存"><a class="markdownIt-Anchor" href="#16-new-和-malloc-如何判断是否申请到内存"></a> 16、new 和 malloc 如何判断是否申请到内存？</h2>
<p>面试高频指数：两星</p>
<hr>
<ul>
<li><code>malloc</code> ：成功申请到内存，返回指向该内存的指针；分配失败，返回 <code>NULL</code> 指针。</li>
<li><code>new</code>：内存分配成功，返回该对象类型的指针；分配失败，抛出 <code>bad_alloc</code> 异常。</li>
</ul>
<h2 id="17-delete-实现原理delete-和-delete-的区别"><a class="markdownIt-Anchor" href="#17-delete-实现原理delete-和-delete-的区别"></a> 17、delete 实现原理？delete 和 delete[] 的区别？</h2>
<p>面试高频指数：三星</p>
<hr>
<p><code>delete</code> 的实现原理：</p>
<ul>
<li>首先执行该对象所属类的析构函数；</li>
<li>进而通过调用 <code>operator delete</code> 的标准库函数来释放所占的内存空间。</li>
</ul>
<p><code>delete</code> 和 <code>delete []</code> 的区别：</p>
<ul>
<li><code>delete</code> 用来释放单个对象所占的空间，只会调用一次析构函数；</li>
<li><code>delete []</code> 用来释放数组空间，会对数组中的每个成员都调用一次析构函数。</li>
</ul>
<h2 id="18-new-和-malloc-的区别delete-和-free-的区别"><a class="markdownIt-Anchor" href="#18-new-和-malloc-的区别delete-和-free-的区别"></a> 18、new 和 malloc 的区别，delete 和 free 的区别</h2>
<p>面试高频指数：四星</p>
<hr>
<p>在使用的时候，<code>new</code>、<code>delete</code> 搭配使用，<code>malloc</code>、<code>free</code> 搭配使用。</p>
<ul>
<li><code>malloc</code>、<code>free</code> 是库函数，而<code>new</code>、<code>delete</code> 是关键字。</li>
<li><code>new</code> 申请空间时，无需指定分配空间的大小，编译器会根据类型自行计算；<code>malloc</code> 在申请空间时，需要确定所申请空间的大小。</li>
<li><code>new</code> 申请空间时，返回的类型是对象的指针类型，无需强制类型转换，是类型安全的操作符；<code>malloc</code> 申请空间时，返回的是 <code>void *</code> 类型，需要进行强制类型的转换，转换为对象类型的指针。</li>
<li><code>new</code> 分配失败时，会抛出<code>bad_alloc</code> 异常，<code>malloc</code> 分配失败时返回空指针。</li>
<li>对于自定义的类型，<code>new</code> 首先调用<code>operator new()</code> 函数申请空间（底层通过<code>malloc</code> 实现），然后调用构造函数进行初始化，最后返回自定义类型的指针；<code>delete</code> 首先调用析构函数，然后调用<code>operator delete()</code> 释放空间（底层通过<code>free</code> 实现）。<code>malloc</code>、<code>free</code> 无法进行自定义类型的对象的构造和析构。</li>
<li><code>new</code> 操作符从自由存储区上为对象动态分配内存，而<code>malloc</code> 函数从堆上动态分配内存。（自由存储区不等于堆）。</li>
</ul>
<h2 id="19-malloc的原理malloc的底层实现"><a class="markdownIt-Anchor" href="#19-malloc的原理malloc的底层实现"></a> 19、malloc的原理？malloc的底层实现？</h2>
<p>面试高频指数：两星</p>
<hr>
<p><code>malloc</code> 的原理：</p>
<ul>
<li>当开辟的空间小于 128K 时，调用 <code>brk()</code> 函数，通过移动 <code>_enddata</code> 来实现；</li>
<li>当开辟的空间大于 128K 时，调用 <code>mmap()</code> 函数，通过在虚拟地址空间中开辟一块内存空间来实现。</li>
</ul>
<p><code>malloc</code> 的底层实现：</p>
<ul>
<li><code>brk()</code> 函数实现原理：向高地址的方向移动指向数据段的高地址的指针<code>_enddata</code>。</li>
<li><code>mmap</code> 内存映射原理：
<ol>
<li>进程启动映射过程，并在虚拟地址空间中为映射创建虚拟映射区域；</li>
<li>调用内核空间的系统调用函数 <code>mmap()</code>，实现文件物理地址和进程虚拟地址的一一映射关系；</li>
<li>进程发起对这片映射空间的访问，引发缺页异常，实现文件内容到物理内存（主存）的拷贝。</li>
</ol>
</li>
</ul>
<h2 id="20-c-和-c-struct-的区别"><a class="markdownIt-Anchor" href="#20-c-和-c-struct-的区别"></a> 20、C 和 C++ struct 的区别？</h2>
<p>面试高频指数：两星</p>
<hr>
<ul>
<li>在 C 语言中<code>struct</code> 是用户自定义数据类型；在 C++ 中 <code>struct</code> 是抽象数据类型，支持成员函数的定义。</li>
<li>C 语言中<code>struct</code> 没有访问权限的设置，是一些变量的集合体，不能定义成员函数；C++ 中 <code>struct</code> 可以和类一样，有访问权限，并可以定义成员函数。</li>
<li>C 语言中 <code>struct</code> 定义的自定义数据类型，在定义该类型的变量时，需要加上 <code>struct</code> 关键字，例如：<code>struct A var;</code>，定义 <code>A</code> 类型的变量；而C++ 中，不用加该关键字，例如：<code>A var;</code></li>
</ul>
<h2 id="21-为什么有了-class-还保留-struct"><a class="markdownIt-Anchor" href="#21-为什么有了-class-还保留-struct"></a> 21、为什么有了 class 还保留 struct</h2>
<p>面试高频指数：两星</p>
<hr>
<ul>
<li>C++ 是在 C 语言的基础上发展起来的，为了与 C 语言兼容，C++ 中保留了 <code>struct</code>。</li>
</ul>
<h2 id="22-struct-和-union-的区别"><a class="markdownIt-Anchor" href="#22-struct-和-union-的区别"></a> 22、struct 和 union 的区别</h2>
<p>面试高频指数：两星</p>
<hr>
<p>说明：<code>union</code> 是联合体，<code>struct</code>是结构体。</p>
<p>区别：</p>
<ol>
<li>联合体和结构体都是由若干个数据类型不同的数据成员组成。使用时，联合体只有一个有效的成员；而结构体所有的成员都有效。</li>
<li>对联合体的不同成员赋值，将会覆盖其他成员的值，而对于结构体的不同成员赋值时，相互不影响。</li>
<li>联合体的大小为其内部所有变量的最大值，按照最大类型的倍数进行分配大小；结构体分配内存的大小遵循内存对齐原则。</li>
</ol>
<figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;iostream&gt;</span></span></span><br><span class="line"><span class="keyword">using</span> <span class="keyword">namespace</span> std;</span><br><span class="line"></span><br><span class="line"><span class="keyword">typedef</span> <span class="class"><span class="keyword">union</span></span></span><br><span class="line"><span class="class">&#123;</span></span><br><span class="line">    <span class="keyword">char</span> c[<span class="number">10</span>];</span><br><span class="line">    <span class="keyword">char</span> cc1; <span class="comment">// char 1 字节，按该类型的倍数分配大小</span></span><br><span class="line">&#125; u11;</span><br><span class="line"></span><br><span class="line"><span class="keyword">typedef</span> <span class="class"><span class="keyword">union</span></span></span><br><span class="line"><span class="class">&#123;</span></span><br><span class="line">    <span class="keyword">char</span> c[<span class="number">10</span>];</span><br><span class="line">    <span class="keyword">int</span> i; <span class="comment">// int 4 字节，按该类型的倍数分配大小</span></span><br><span class="line">&#125; u22;</span><br><span class="line"></span><br><span class="line"><span class="keyword">typedef</span> <span class="class"><span class="keyword">union</span></span></span><br><span class="line"><span class="class">&#123;</span></span><br><span class="line">    <span class="keyword">char</span> c[<span class="number">10</span>];</span><br><span class="line">    <span class="keyword">double</span> d; <span class="comment">// double 8 字节，按该类型的倍数分配大小</span></span><br><span class="line">&#125; u33;</span><br><span class="line"></span><br><span class="line"><span class="keyword">typedef</span> <span class="class"><span class="keyword">struct</span> <span class="title">s1</span></span></span><br><span class="line"><span class="class">&#123;</span></span><br><span class="line">    <span class="keyword">char</span> c;   <span class="comment">// 1 字节</span></span><br><span class="line">    <span class="keyword">double</span> d; <span class="comment">// 1（char）+ 7（内存对齐）+ 8（double）= 16 字节</span></span><br><span class="line">&#125; s11;</span><br><span class="line"></span><br><span class="line"><span class="keyword">typedef</span> <span class="class"><span class="keyword">struct</span> <span class="title">s2</span></span></span><br><span class="line"><span class="class">&#123;</span></span><br><span class="line">    <span class="keyword">char</span> c;   <span class="comment">// 1 字节</span></span><br><span class="line">    <span class="keyword">char</span> cc;  <span class="comment">// 1（char）+ 1（char）= 2 字节</span></span><br><span class="line">    <span class="keyword">double</span> d; <span class="comment">// 2 + 6（内存对齐）+ 8（double）= 16 字节</span></span><br><span class="line">&#125; s22;</span><br><span class="line"></span><br><span class="line"><span class="keyword">typedef</span> <span class="class"><span class="keyword">struct</span> <span class="title">s3</span></span></span><br><span class="line"><span class="class">&#123;</span></span><br><span class="line">    <span class="keyword">char</span> c;   <span class="comment">// 1 字节</span></span><br><span class="line">    <span class="keyword">double</span> d; <span class="comment">// 1（char）+ 7（内存对齐）+ 8（double）= 16 字节</span></span><br><span class="line">    <span class="keyword">char</span> cc;  <span class="comment">// 16 + 1（char）+ 7（内存对齐）= 24 字节</span></span><br><span class="line">&#125; s33;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">int</span> <span class="title">main</span><span class="params">()</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">    cout &lt;&lt; <span class="built_in"><span class="keyword">sizeof</span></span>(u11) &lt;&lt; endl; <span class="comment">// 10</span></span><br><span class="line">    cout &lt;&lt; <span class="built_in"><span class="keyword">sizeof</span></span>(u22) &lt;&lt; endl; <span class="comment">// 12</span></span><br><span class="line">    cout &lt;&lt; <span class="built_in"><span class="keyword">sizeof</span></span>(u33) &lt;&lt; endl; <span class="comment">// 16</span></span><br><span class="line">    cout &lt;&lt; <span class="built_in"><span class="keyword">sizeof</span></span>(s11) &lt;&lt; endl; <span class="comment">// 16</span></span><br><span class="line">    cout &lt;&lt; <span class="built_in"><span class="keyword">sizeof</span></span>(s22) &lt;&lt; endl; <span class="comment">// 16</span></span><br><span class="line">    cout &lt;&lt; <span class="built_in"><span class="keyword">sizeof</span></span>(s33) &lt;&lt; endl; <span class="comment">// 24</span></span><br><span class="line"></span><br><span class="line">    cout &lt;&lt; <span class="built_in"><span class="keyword">sizeof</span></span>(<span class="keyword">int</span>) &lt;&lt; endl;    <span class="comment">// 4</span></span><br><span class="line">    cout &lt;&lt; <span class="built_in"><span class="keyword">sizeof</span></span>(<span class="keyword">double</span>) &lt;&lt; endl; <span class="comment">// 8</span></span><br><span class="line">    <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<h2 id="23-class-和-struct-的异同"><a class="markdownIt-Anchor" href="#23-class-和-struct-的异同"></a> 23、class 和 struct 的异同</h2>
<p>面试高频指数：两星</p>
<hr>
<ul>
<li><code>struct</code> 和 <code>class</code> 都可以自定义数据类型，也支持继承操作。</li>
<li><code>struct</code> 中默认的访问级别是 <code>public</code>，默认的继承级别也是 <code>public</code>；<code>class</code> 中默认的访问级别是 <code>private</code>，默认的继承级别也是<code>private</code>。</li>
<li>当<code>class</code>继承 <code>struct</code> 或者 <code>struct</code> 继承 <code>class</code> 时，默认的继承级别取决于 <code>class</code> 或 <code>struct</code> 本身，<code>class</code>（<code>private</code>继承）、<code>struct</code>(<code>public</code>继承)，即取决于派生类的默认继承级别。</li>
</ul>
<figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="class"><span class="keyword">struct</span> <span class="title">A</span>&#123;</span>&#125;；</span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">B</span> :</span> A&#123;&#125;; <span class="comment">// private 继承 </span></span><br><span class="line"><span class="class"><span class="keyword">struct</span> <span class="title">C</span> :</span> B&#123;&#125;； <span class="comment">// public 继承</span></span><br></pre></td></tr></table></figure>
<p>举例：</p>
<figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="meta-keyword">include</span><span class="meta-string">&lt;iostream&gt;</span></span></span><br><span class="line"></span><br><span class="line"><span class="keyword">using</span> <span class="keyword">namespace</span> std;</span><br><span class="line"></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">A</span>&#123;</span></span><br><span class="line"><span class="keyword">public</span>:</span><br><span class="line">    <span class="function"><span class="keyword">void</span> <span class="title">funA</span><span class="params">()</span></span>&#123;</span><br><span class="line">        cout &lt;&lt; <span class="string">&quot;class A&quot;</span> &lt;&lt; endl;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;;</span><br><span class="line"></span><br><span class="line"><span class="class"><span class="keyword">struct</span> <span class="title">B</span>:</span> A&#123; <span class="comment">// 由于 B 是 struct，A 的默认继承级别为 public</span></span><br><span class="line"><span class="keyword">public</span>:</span><br><span class="line">    <span class="function"><span class="keyword">void</span> <span class="title">funB</span><span class="params">()</span></span>&#123;</span><br><span class="line">        cout &lt;&lt; <span class="string">&quot;class B&quot;</span> &lt;&lt; endl;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;;</span><br><span class="line"></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">C</span>:</span> B&#123; <span class="comment">// 由于 C 是 class，B 的默认继承级别为 private，所以无法访问基类 B 中的 printB 函数</span></span><br><span class="line"></span><br><span class="line">&#125;;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">int</span> <span class="title">main</span><span class="params">()</span></span>&#123;</span><br><span class="line">    A ex1;</span><br><span class="line">    ex1.<span class="built_in">funA</span>(); <span class="comment">// class A</span></span><br><span class="line"></span><br><span class="line">    B ex2;</span><br><span class="line">    ex2.<span class="built_in">funA</span>(); <span class="comment">// class A</span></span><br><span class="line">    ex2.<span class="built_in">funB</span>(); <span class="comment">// class B</span></span><br><span class="line"></span><br><span class="line">    C ex3;</span><br><span class="line">    ex3.<span class="built_in">funB</span>(); <span class="comment">// error: &#x27;B&#x27; is not an accessible base of &#x27;C&#x27;.</span></span><br><span class="line">    <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<ul>
<li><code>class</code> 可以用于定义模板参数，<code>struct</code> 不能用于定义模板参数。</li>
</ul>
<h2 id="24-volatile-的作用是否具有原子性对编译器有什么影响"><a class="markdownIt-Anchor" href="#24-volatile-的作用是否具有原子性对编译器有什么影响"></a> 24、volatile 的作用？是否具有原子性，对编译器有什么影响？</h2>
<p>面试高频指数：两星</p>
<hr>
<p><code>volatile</code> 的作用：当对象的值可能在程序的控制或检测之外被改变时，应该将该对象声明为<code>volatile</code>，告知编译器不应对这样的对象进行优化。</p>
<p><code>volatile</code> 不具有原子性。</p>
<p><code>volatile</code> 对编译器的影响：使用该关键字后，编译器不会对相应的对象进行优化，即不会将变量从内存缓存到寄存器中，防止多个线程有可能使用内存中的变量，有可能使用寄存器中的变量，从而导致程序错误。</p>
<h2 id="25-什么情况下一定要用-volatile能否和-const-一起使用"><a class="markdownIt-Anchor" href="#25-什么情况下一定要用-volatile能否和-const-一起使用"></a> 25、什么情况下一定要用 volatile，能否和 const 一起使用？</h2>
<p>面试高频指数：两星</p>
<hr>
<p>使用<code>volatile</code>关键字的场景：</p>
<ul>
<li>当多个线程都会用到某一变量，并且该变量的值有可能发生改变时，需要用<code>volatile</code> 关键字对该变量进行修饰；</li>
<li>中断服务程序中访问的变量或并行设备的硬件寄存器的变量，最好用<code>volatile</code> 关键字修饰。</li>
</ul>
<p><code>volatile</code> 关键字和 <code>const</code> 关键字可以同时使用，某种类型可以既是 <code>volatile</code> 又是 <code>const</code>，同时具有二者的属性。</p>
<h2 id="26-返回函数中静态变量的地址会发生什么"><a class="markdownIt-Anchor" href="#26-返回函数中静态变量的地址会发生什么"></a> 26、返回函数中静态变量的地址会发生什么？</h2>
<p>面试高频指数：两星</p>
<hr>
<figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;iostream&gt;</span></span></span><br><span class="line"><span class="keyword">using</span> <span class="keyword">namespace</span> std;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">int</span> * <span class="title">fun</span><span class="params">(<span class="keyword">int</span> tmp)</span></span>&#123;</span><br><span class="line">    <span class="keyword">static</span> <span class="keyword">int</span> var = <span class="number">10</span>;</span><br><span class="line">    var *= tmp;</span><br><span class="line">    <span class="keyword">return</span> &amp;var;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">int</span> <span class="title">main</span><span class="params">()</span> </span>&#123;</span><br><span class="line">    cout &lt;&lt; *<span class="built_in">fun</span>(<span class="number">5</span>) &lt;&lt; endl;</span><br><span class="line">    <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="comment">/*</span></span><br><span class="line"><span class="comment">运行结果：</span></span><br><span class="line"><span class="comment">50</span></span><br><span class="line"><span class="comment">*/</span></span><br></pre></td></tr></table></figure>
<p>说明：上述代码中在函数 <code>fun</code> 中定义了静态局部变量 <code>var</code>，使得离开该函数的作用域后，该变量不会销毁，返回到主函数中，该变量依然存在，从而使程序得到正确的运行结果。但是，该静态局部变量直到程序运行结束后才销毁，浪费内存空间。</p>
<h2 id="27-extern-c-的作用"><a class="markdownIt-Anchor" href="#27-extern-c-的作用"></a> 27、extern C 的作用？</h2>
<p>面试高频指数：两星</p>
<hr>
<p>当 C++ 程序 需要调用 C 语言编写的函数，C++ 使用链接指示，即 <code>extern &quot;C&quot;</code> 指出任意非 C++ 函数所用的语言。</p>
<p>换个容易理解的说法：<code>extern &quot;C&quot;</code> 的作用是让 C++ 编译器将 <code>extern &quot;C&quot;</code> 声明的代码当做  C 语言代码处理，可以避免 C++ 因符号修饰导致代码不能和 C 语言库中的符号进行链接的问题。</p>
<p>C++ 和 C 语言编译函数签名方式不一样，<code>extern</code> 关键字可以让两者保持统一，这样才能找到对应的函数。</p>
<p>举例：</p>
<figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 可能出现在 C++ 头文件&lt;cstring&gt;中的链接指示</span></span><br><span class="line"><span class="keyword">extern</span> <span class="string">&quot;C&quot;</span>&#123;</span><br><span class="line">    <span class="function"><span class="keyword">int</span> <span class="title">strcmp</span><span class="params">(<span class="keyword">const</span> <span class="keyword">char</span>*, <span class="keyword">const</span> <span class="keyword">char</span>*)</span></span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<h2 id="28-sizeof1-1-在-c-和-c-中分别是什么结果"><a class="markdownIt-Anchor" href="#28-sizeof1-1-在-c-和-c-中分别是什么结果"></a> 28、sizeof(1 == 1) 在 C 和 C++ 中分别是什么结果？</h2>
<p>面试高频指数：1星</p>
<hr>
<p>C 语言代码：</p>
<figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="meta-keyword">include</span><span class="meta-string">&lt;stdio.h&gt;</span></span></span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">void</span> <span class="title">main</span><span class="params">()</span></span>&#123;</span><br><span class="line">    <span class="built_in">printf</span>(<span class="string">&quot;%d\n&quot;</span>, <span class="keyword">sizeof</span>(<span class="number">1</span>==<span class="number">1</span>)); <span class="comment">//整数1</span></span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="comment">/*</span></span><br><span class="line"><span class="comment">运行结果：</span></span><br><span class="line"><span class="comment">4</span></span><br><span class="line"><span class="comment">*/</span></span><br></pre></td></tr></table></figure>
<p>C++ 代码：</p>
<figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;iostream&gt;</span></span></span><br><span class="line"><span class="keyword">using</span> <span class="keyword">namespace</span> std;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">int</span> <span class="title">main</span><span class="params">()</span> </span>&#123;</span><br><span class="line">    cout &lt;&lt; <span class="built_in"><span class="keyword">sizeof</span></span>(<span class="number">1</span>==<span class="number">1</span>) &lt;&lt; endl; <span class="comment">//布尔类型</span></span><br><span class="line">    <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="comment">/*</span></span><br><span class="line"><span class="comment">1</span></span><br><span class="line"><span class="comment">*/</span></span><br></pre></td></tr></table></figure>
<h2 id="29-memcpy-函数的底层原理"><a class="markdownIt-Anchor" href="#29-memcpy-函数的底层原理"></a> 29、memcpy 函数的底层原理？</h2>
<p>面试高频指数：三星</p>
<hr>
<figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">void</span> *<span class="title">memcpy</span><span class="params">(<span class="keyword">void</span> *dst, <span class="keyword">const</span> <span class="keyword">void</span> *src, <span class="keyword">size_t</span> size)</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">    <span class="keyword">char</span> *psrc;</span><br><span class="line">    <span class="keyword">char</span> *pdst;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">if</span> (<span class="literal">NULL</span> == dst || <span class="literal">NULL</span> == src)</span><br><span class="line">    &#123;</span><br><span class="line">        <span class="keyword">return</span> <span class="literal">NULL</span>;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">if</span> ((src &lt; dst) &amp;&amp; (<span class="keyword">char</span> *)src + size &gt; (<span class="keyword">char</span> *)dst) <span class="comment">// 出现地址重叠的情况，自后向前拷贝</span></span><br><span class="line">    &#123;</span><br><span class="line">        psrc = (<span class="keyword">char</span> *)src + size - <span class="number">1</span>;</span><br><span class="line">        pdst = (<span class="keyword">char</span> *)dst + size - <span class="number">1</span>;</span><br><span class="line">        <span class="keyword">while</span> (size--)</span><br><span class="line">        &#123;</span><br><span class="line">            *pdst-- = *psrc--;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">else</span></span><br><span class="line">    &#123;</span><br><span class="line">        psrc = (<span class="keyword">char</span> *)src;</span><br><span class="line">        pdst = (<span class="keyword">char</span> *)dst;</span><br><span class="line">        <span class="keyword">while</span> (size--)</span><br><span class="line">        &#123;</span><br><span class="line">            *pdst++ = *psrc++;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">return</span> dst;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p><a target="_blank" rel="noopener" href="https://blog.csdn.net/yuanrxdu/article/details/23771459">https://blog.csdn.net/yuanrxdu/article/details/23771459</a></p>
<h2 id="30-strcpy-函数有什么缺陷"><a class="markdownIt-Anchor" href="#30-strcpy-函数有什么缺陷"></a> 30、strcpy 函数有什么缺陷？</h2>
<p>面试高频指数：两星</p>
<hr>
<p><code>strcpy</code> 函数的缺陷：<code>strcpy</code> 函数不检查目的缓冲区的大小边界，而是将源字符串逐一地全部赋值给目的字符串地址起始的一块连续的内存，同时加上字符串终止符，会导致其它变量被覆盖。</p>
<figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;iostream&gt;</span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;cstring&gt;</span></span></span><br><span class="line"><span class="keyword">using</span> <span class="keyword">namespace</span> std;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">int</span> <span class="title">main</span><span class="params">()</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">    <span class="keyword">int</span> var = <span class="number">0x11112222</span>;</span><br><span class="line">    <span class="keyword">char</span> arr[<span class="number">10</span>];</span><br><span class="line">    cout &lt;&lt; <span class="string">&quot;Address : var &quot;</span> &lt;&lt; &amp;var &lt;&lt; endl;</span><br><span class="line">    cout &lt;&lt; <span class="string">&quot;Address : arr &quot;</span> &lt;&lt; &amp;arr &lt;&lt; endl;</span><br><span class="line">    <span class="built_in">strcpy</span>(arr, <span class="string">&quot;hello world!&quot;</span>);</span><br><span class="line">    cout &lt;&lt; <span class="string">&quot;var:&quot;</span> &lt;&lt; hex &lt;&lt; var &lt;&lt; endl; <span class="comment">// 将变量 var 以 16 进制输出</span></span><br><span class="line">    cout &lt;&lt; <span class="string">&quot;arr:&quot;</span> &lt;&lt; arr &lt;&lt; endl;</span><br><span class="line">    <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="comment">/*</span></span><br><span class="line"><span class="comment">Address : var 0x23fe4c</span></span><br><span class="line"><span class="comment">Address : arr 0x23fe42</span></span><br><span class="line"><span class="comment">var:11002164</span></span><br><span class="line"><span class="comment">arr:hello world!</span></span><br><span class="line"><span class="comment">*/</span></span><br></pre></td></tr></table></figure>
<p>说明：从上述代码可以看出，变量 <code>var</code> 的后六位被字符串 <code>&quot;hello world!&quot;</code> 的 <code>&quot;d!\0&quot;</code> 这三个字符改变，这三个字符对应的 ascii 码的十六进制为：<code>\0</code>(0x00)，<code>!</code>(0x21)，<code>d</code>(0x64)。</p>
<p>原因：变量 <code>arr</code> 只分配的 10 个内存空间，通过上述程序中的地址可以看出 <code>arr</code> 和 <code>var</code> 在内存中是连续存放的，但是在调用 <code>strcpy</code> 函数进行拷贝时，源字符串 <code>&quot;hello world!&quot;</code> 所占的内存空间为 13，因此在拷贝的过程中会占用 <code>var</code> 的内存空间，导致 <code>var</code> 的后六位被覆盖。</p>
<p>图解：</p>
<p><img src="https://pic.leetcode-cn.com/1627822193-yqLShF-image.png" alt="image.png"></p>
<h2 id="31-auto-类型推导的原理"><a class="markdownIt-Anchor" href="#31-auto-类型推导的原理"></a> 31、auto 类型推导的原理</h2>
<p>面试高频指数：两星</p>
<hr>
<p><code>auto</code> 类型推导的原理：编译器根据初始值来推算变量的类型，要求用 <code>auto</code> 定义变量时必须有初始值。编译器推断出来的 <code>auto</code> 类型有时和初始值类型并不完全一样，编译器会适当改变结果类型使其更符合初始化规则。</p>
<h1 id="五-类相关"><a class="markdownIt-Anchor" href="#五-类相关"></a> 五、类相关</h1>
<h2 id="1-什么是虚函数什么是纯虚函数"><a class="markdownIt-Anchor" href="#1-什么是虚函数什么是纯虚函数"></a> 1、什么是虚函数？什么是纯虚函数？</h2>
<p>面试高频指数：五星</p>
<hr>
<p><strong>虚函数：</strong> 被 <code>virtual</code> 关键字修饰的成员函数，就是虚函数。</p>
<figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;iostream&gt;</span></span></span><br><span class="line"><span class="keyword">using</span> <span class="keyword">namespace</span> std;</span><br><span class="line"></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">A</span></span></span><br><span class="line"><span class="class">&#123;</span></span><br><span class="line"><span class="keyword">public</span>:</span><br><span class="line">    <span class="function"><span class="keyword">virtual</span> <span class="keyword">void</span> <span class="title">v_fun</span><span class="params">()</span> <span class="comment">// 虚函数</span></span></span><br><span class="line"><span class="function">    </span>&#123;</span><br><span class="line">        cout &lt;&lt; <span class="string">&quot;A::v_fun()&quot;</span> &lt;&lt; endl;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;;</span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">B</span> :</span> <span class="keyword">public</span> A</span><br><span class="line">&#123;</span><br><span class="line"><span class="keyword">public</span>:</span><br><span class="line">    <span class="function"><span class="keyword">void</span> <span class="title">v_fun</span><span class="params">()</span></span></span><br><span class="line"><span class="function">    </span>&#123;</span><br><span class="line">        cout &lt;&lt; <span class="string">&quot;B::v_fun()&quot;</span> &lt;&lt; endl;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;;</span><br><span class="line"><span class="function"><span class="keyword">int</span> <span class="title">main</span><span class="params">()</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">    A *p = <span class="keyword">new</span> <span class="built_in">B</span>();</span><br><span class="line">    p-&gt;<span class="built_in">v_fun</span>(); <span class="comment">// B::v_fun()</span></span><br><span class="line">    <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p><strong>纯虚函数：</strong></p>
<ul>
<li>纯虚函数在类中声明时，加上<code>=0</code>；</li>
<li>含有纯虚函数的类称为抽象类（只要有纯虚函数这个类就是抽象类），类中只有接口，没有具体的实现方法；</li>
<li>继承纯虚函数的派生类，如果没有完全实现基类纯虚函数，依然是抽象类，不能实例化对象。</li>
</ul>
<p>说明：</p>
<ul>
<li>抽象类对象不能作为函数的参数，不能创建对象，不能作为函数返回类型；</li>
<li>可以声明抽象类指针，可以声明抽象类的引用；</li>
<li>子类必须继承父类的纯虚函数，并全部实现后，才能创建子类的对象。</li>
</ul>
<h2 id="2-虚函数和纯虚函数的区别"><a class="markdownIt-Anchor" href="#2-虚函数和纯虚函数的区别"></a> 2、虚函数和纯虚函数的区别？</h2>
<p>面试高频指数：三星</p>
<hr>
<ul>
<li>虚函数和纯虚函数可以出现在同一个类中，该类称为抽象虚类。（含有纯虚函数的类被称为抽象基类）</li>
<li>使用方式不同：虚函数可以直接使用，纯虚函数必须在派生类中实现后才能使用；</li>
<li>定义形式不同：虚函数在定义时在普通函数的基础上加上 <code>virtual</code> 关键字，纯虚函数定义时除了加上 <code>virtual</code> 关键字还需要加上 <code>=0</code>；</li>
<li>虚函数必须实现，否贼编译器会报错。</li>
<li>对于实现纯虚函数的派生类，该纯虚函数在派生类中被称为虚函数，虚函数和纯虚函数都可以在派生类中重写；</li>
<li>析构函数最好定义为虚函数，特别是对于含有继承关系的类；析构函数可以定义为纯虚函数，此时，其所在的类为抽象基类，不能创建实例化对象。</li>
</ul>
<h2 id="3-虚函数的实现机制"><a class="markdownIt-Anchor" href="#3-虚函数的实现机制"></a> 3、虚函数的实现机制</h2>
<p>面试高频指数：五星</p>
<hr>
<p><strong>实现机制：</strong> 虚函数通过虚函数表来实现。虚函数的地址保存在虚函数表中，在类的对象所在的内存空间中，保存了指向虚函数表的指针（称为”虚表指针“），通过虚表指针可以找到类对应的虚函数表。虚函数表解决了基类和派生类的继承问题和类中成员函数的覆盖问题，当用基类的指针来操作一个派生类的时候，这张虚函数表就指明了实际应该调用的函数。</p>
<p><strong>虚函数表相关知识点：</strong></p>
<ul>
<li>虚函数表存放的内容：类的虚函数的地址。</li>
<li>虚函数表建立的时间：编译阶段，即程序的编译过程中会将虚函数的地址放在虚函数表中。</li>
<li>虚表指针保存的位置：虚表指针存放在对象的内存空间中最前面的位置，这是为了保证正确取到虚函数的偏移量。</li>
</ul>
<p>注：虚函数表和类绑定，虚表指针和对象绑定。即类的不同的对象的虚函数表是一样的，但是每个对象都有自己的虚表指针，来指向类的虚函数表。</p>
<p><strong>实例：</strong></p>
<p>无虚函数覆盖的情况：</p>
<figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;iostream&gt;</span></span></span><br><span class="line"><span class="keyword">using</span> <span class="keyword">namespace</span> std;</span><br><span class="line"></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Base</span></span></span><br><span class="line"><span class="class">&#123;</span></span><br><span class="line"><span class="keyword">public</span>:</span><br><span class="line">    <span class="function"><span class="keyword">virtual</span> <span class="keyword">void</span> <span class="title">B_fun1</span><span class="params">()</span> </span>&#123; cout &lt;&lt; <span class="string">&quot;Base::B_fun1()&quot;</span> &lt;&lt; endl; &#125;</span><br><span class="line">    <span class="function"><span class="keyword">virtual</span> <span class="keyword">void</span> <span class="title">B_fun2</span><span class="params">()</span> </span>&#123; cout &lt;&lt; <span class="string">&quot;Base::B_fun2()&quot;</span> &lt;&lt; endl; &#125;</span><br><span class="line">    <span class="function"><span class="keyword">virtual</span> <span class="keyword">void</span> <span class="title">B_fun3</span><span class="params">()</span> </span>&#123; cout &lt;&lt; <span class="string">&quot;Base::B_fun3()&quot;</span> &lt;&lt; endl; &#125;</span><br><span class="line">&#125;;</span><br><span class="line"></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Derive</span> :</span> <span class="keyword">public</span> Base</span><br><span class="line">&#123;</span><br><span class="line"><span class="keyword">public</span>:</span><br><span class="line">    <span class="function"><span class="keyword">virtual</span> <span class="keyword">void</span> <span class="title">D_fun1</span><span class="params">()</span> </span>&#123; cout &lt;&lt; <span class="string">&quot;Derive::D_fun1()&quot;</span> &lt;&lt; endl; &#125;</span><br><span class="line">    <span class="function"><span class="keyword">virtual</span> <span class="keyword">void</span> <span class="title">D_fun2</span><span class="params">()</span> </span>&#123; cout &lt;&lt; <span class="string">&quot;Derive::D_fun2()&quot;</span> &lt;&lt; endl; &#125;</span><br><span class="line">    <span class="function"><span class="keyword">virtual</span> <span class="keyword">void</span> <span class="title">D_fun3</span><span class="params">()</span> </span>&#123; cout &lt;&lt; <span class="string">&quot;Derive::D_fun3()&quot;</span> &lt;&lt; endl; &#125;</span><br><span class="line">&#125;;</span><br><span class="line"><span class="function"><span class="keyword">int</span> <span class="title">main</span><span class="params">()</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">    Base *p = <span class="keyword">new</span> <span class="built_in">Derive</span>();</span><br><span class="line">    p-&gt;<span class="built_in">B_fun1</span>(); <span class="comment">// Base::B_fun1()</span></span><br><span class="line">    <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>基类和派生类的继承关系：</p>
<p><img src="https://pic.leetcode-cn.com/1612681846-tyqCUP-image.png" alt="image.png"></p>
<p>基类的虚函数表：</p>
<p><img src="https://pic.leetcode-cn.com/1612679161-OtbPhj-image.png" alt="image.png"></p>
<p>派生类的虚函数表：</p>
<p><img src="https://pic.leetcode-cn.com/1612681900-RShiIP-image.png" alt="image.png"></p>
<p>主函数中基类的指针 <code>p</code> 指向了派生类的对象，当调用函数 <code>B_fun1()</code> 时，通过派生类的虚函数表找到该函数的地址，从而完成调用。</p>
<h2 id="4-单继承和多继承的虚函数表结构"><a class="markdownIt-Anchor" href="#4-单继承和多继承的虚函数表结构"></a> 4、单继承和多继承的虚函数表结构</h2>
<p>面试高频指数：四星</p>
<hr>
<p><strong>编译器处理虚函数表：</strong></p>
<ul>
<li>编译器将虚函数表的指针放在类的实例对象的内存空间中，该对象调用该类的虚函数时，通过指针找到虚函数表，根据虚函数表中存放的虚函数的地址找到对应的虚函数。</li>
<li>如果派生类没有重新定义基类的虚函数 A，则派生类的虚函数表中保存的是基类的虚函数  A 的地址，也就是说基类和派生类的虚函数  A 的地址是一样的。</li>
<li>如果派生类重写了基类的某个虚函数 B，则派生的虚函数表中保存的是重写后的虚函数 B 的地址，也就是说虚函数 B 有两个版本，分别存放在基类和派生类的虚函数表中。</li>
<li>如果派生类重新定义了新的虚函数  C，派生类的虚函数表保存新的虚函数 C 的地址。</li>
</ul>
<ol>
<li>
<p>单继承无虚函数覆盖的情况：</p>
 <figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;iostream&gt;</span></span></span><br><span class="line"><span class="keyword">using</span> <span class="keyword">namespace</span> std;</span><br><span class="line"></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Base</span></span></span><br><span class="line"><span class="class">&#123;</span></span><br><span class="line"><span class="keyword">public</span>:</span><br><span class="line">    <span class="function"><span class="keyword">virtual</span> <span class="keyword">void</span> <span class="title">B_fun1</span><span class="params">()</span> </span>&#123; cout &lt;&lt; <span class="string">&quot;Base::B_fun1()&quot;</span> &lt;&lt; endl; &#125;</span><br><span class="line">    <span class="function"><span class="keyword">virtual</span> <span class="keyword">void</span> <span class="title">B_fun2</span><span class="params">()</span> </span>&#123; cout &lt;&lt; <span class="string">&quot;Base::B_fun2()&quot;</span> &lt;&lt; endl; &#125;</span><br><span class="line">    <span class="function"><span class="keyword">virtual</span> <span class="keyword">void</span> <span class="title">B_fun3</span><span class="params">()</span> </span>&#123; cout &lt;&lt; <span class="string">&quot;Base::B_fun3()&quot;</span> &lt;&lt; endl; &#125;</span><br><span class="line">&#125;;</span><br><span class="line"></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Derive</span> :</span> <span class="keyword">public</span> Base</span><br><span class="line">&#123;</span><br><span class="line"><span class="keyword">public</span>:</span><br><span class="line">    <span class="function"><span class="keyword">virtual</span> <span class="keyword">void</span> <span class="title">D_fun1</span><span class="params">()</span> </span>&#123; cout &lt;&lt; <span class="string">&quot;Derive::D_fun1()&quot;</span> &lt;&lt; endl; &#125;</span><br><span class="line">    <span class="function"><span class="keyword">virtual</span> <span class="keyword">void</span> <span class="title">D_fun2</span><span class="params">()</span> </span>&#123; cout &lt;&lt; <span class="string">&quot;Derive::D_fun2()&quot;</span> &lt;&lt; endl; &#125;</span><br><span class="line">    <span class="function"><span class="keyword">virtual</span> <span class="keyword">void</span> <span class="title">D_fun3</span><span class="params">()</span> </span>&#123; cout &lt;&lt; <span class="string">&quot;Derive::D_fun3()&quot;</span> &lt;&lt; endl; &#125;</span><br><span class="line">&#125;;</span><br><span class="line"><span class="function"><span class="keyword">int</span> <span class="title">main</span><span class="params">()</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">    Base *p = <span class="keyword">new</span> <span class="built_in">Derive</span>();</span><br><span class="line">    p-&gt;<span class="built_in">B_fun1</span>(); <span class="comment">// Base::B_fun1()</span></span><br><span class="line">    <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>基类和派生类的继承关系：</p>
<p><img src="https://pic.leetcode-cn.com/1612681846-tyqCUP-image.png" alt="image.png"></p>
<p>基类的虚函数表：</p>
<p><img src="https://pic.leetcode-cn.com/1612679161-OtbPhj-image.png" alt="image.png"></p>
<p>派生类的虚函数表：</p>
<p><img src="https://pic.leetcode-cn.com/1612681900-RShiIP-image.png" alt="image.png"></p>
<ol start="2">
<li>
<p>单继承有虚函数覆盖的情况：</p>
 <figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;iostream&gt;</span></span></span><br><span class="line"><span class="keyword">using</span> <span class="keyword">namespace</span> std;</span><br><span class="line"></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Base</span></span></span><br><span class="line"><span class="class">&#123;</span></span><br><span class="line"><span class="keyword">public</span>:</span><br><span class="line">    <span class="function"><span class="keyword">virtual</span> <span class="keyword">void</span> <span class="title">fun1</span><span class="params">()</span> </span>&#123; cout &lt;&lt; <span class="string">&quot;Base::fun1()&quot;</span> &lt;&lt; endl; &#125;</span><br><span class="line">    <span class="function"><span class="keyword">virtual</span> <span class="keyword">void</span> <span class="title">B_fun2</span><span class="params">()</span> </span>&#123; cout &lt;&lt; <span class="string">&quot;Base::B_fun2()&quot;</span> &lt;&lt; endl; &#125;</span><br><span class="line">    <span class="function"><span class="keyword">virtual</span> <span class="keyword">void</span> <span class="title">B_fun3</span><span class="params">()</span> </span>&#123; cout &lt;&lt; <span class="string">&quot;Base::B_fun3()&quot;</span> &lt;&lt; endl; &#125;</span><br><span class="line">&#125;;</span><br><span class="line"></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Derive</span> :</span> <span class="keyword">public</span> Base</span><br><span class="line">&#123;</span><br><span class="line"><span class="keyword">public</span>:</span><br><span class="line">    <span class="function"><span class="keyword">virtual</span> <span class="keyword">void</span> <span class="title">fun1</span><span class="params">()</span> </span>&#123; cout &lt;&lt; <span class="string">&quot;Derive::fun1()&quot;</span> &lt;&lt; endl; &#125;</span><br><span class="line">    <span class="function"><span class="keyword">virtual</span> <span class="keyword">void</span> <span class="title">D_fun2</span><span class="params">()</span> </span>&#123; cout &lt;&lt; <span class="string">&quot;Derive::D_fun2()&quot;</span> &lt;&lt; endl; &#125;</span><br><span class="line">    <span class="function"><span class="keyword">virtual</span> <span class="keyword">void</span> <span class="title">D_fun3</span><span class="params">()</span> </span>&#123; cout &lt;&lt; <span class="string">&quot;Derive::D_fun3()&quot;</span> &lt;&lt; endl; &#125;</span><br><span class="line">&#125;;</span><br><span class="line"><span class="function"><span class="keyword">int</span> <span class="title">main</span><span class="params">()</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">    Base *p = <span class="keyword">new</span> <span class="built_in">Derive</span>();</span><br><span class="line">    p-&gt;<span class="built_in">fun1</span>(); <span class="comment">// Derive::fun1()</span></span><br><span class="line">    <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>派生类的虚函数表：</p>
<p><img src="https://pic.leetcode-cn.com/1612682073-uNdCTl-image.png" alt="image.png"></p>
</li>
<li>
<p>多继承无虚函数覆盖的情况：</p>
 <figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;iostream&gt;</span></span></span><br><span class="line"><span class="keyword">using</span> <span class="keyword">namespace</span> std;</span><br><span class="line"></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Base1</span></span></span><br><span class="line"><span class="class">&#123;</span></span><br><span class="line"><span class="keyword">public</span>:</span><br><span class="line">    <span class="function"><span class="keyword">virtual</span> <span class="keyword">void</span> <span class="title">B1_fun1</span><span class="params">()</span> </span>&#123; cout &lt;&lt; <span class="string">&quot;Base1::B1_fun1()&quot;</span> &lt;&lt; endl; &#125;</span><br><span class="line">    <span class="function"><span class="keyword">virtual</span> <span class="keyword">void</span> <span class="title">B1_fun2</span><span class="params">()</span> </span>&#123; cout &lt;&lt; <span class="string">&quot;Base1::B1_fun2()&quot;</span> &lt;&lt; endl; &#125;</span><br><span class="line">    <span class="function"><span class="keyword">virtual</span> <span class="keyword">void</span> <span class="title">B1_fun3</span><span class="params">()</span> </span>&#123; cout &lt;&lt; <span class="string">&quot;Base1::B1_fun3()&quot;</span> &lt;&lt; endl; &#125;</span><br><span class="line">&#125;;</span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Base2</span></span></span><br><span class="line"><span class="class">&#123;</span></span><br><span class="line"><span class="keyword">public</span>:</span><br><span class="line">    <span class="function"><span class="keyword">virtual</span> <span class="keyword">void</span> <span class="title">B2_fun1</span><span class="params">()</span> </span>&#123; cout &lt;&lt; <span class="string">&quot;Base2::B2_fun1()&quot;</span> &lt;&lt; endl; &#125;</span><br><span class="line">    <span class="function"><span class="keyword">virtual</span> <span class="keyword">void</span> <span class="title">B2_fun2</span><span class="params">()</span> </span>&#123; cout &lt;&lt; <span class="string">&quot;Base2::B2_fun2()&quot;</span> &lt;&lt; endl; &#125;</span><br><span class="line">    <span class="function"><span class="keyword">virtual</span> <span class="keyword">void</span> <span class="title">B2_fun3</span><span class="params">()</span> </span>&#123; cout &lt;&lt; <span class="string">&quot;Base2::B2_fun3()&quot;</span> &lt;&lt; endl; &#125;</span><br><span class="line">&#125;;</span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Base3</span></span></span><br><span class="line"><span class="class">&#123;</span></span><br><span class="line"><span class="keyword">public</span>:</span><br><span class="line">    <span class="function"><span class="keyword">virtual</span> <span class="keyword">void</span> <span class="title">B3_fun1</span><span class="params">()</span> </span>&#123; cout &lt;&lt; <span class="string">&quot;Base3::B3_fun1()&quot;</span> &lt;&lt; endl; &#125;</span><br><span class="line">    <span class="function"><span class="keyword">virtual</span> <span class="keyword">void</span> <span class="title">B3_fun2</span><span class="params">()</span> </span>&#123; cout &lt;&lt; <span class="string">&quot;Base3::B3_fun2()&quot;</span> &lt;&lt; endl; &#125;</span><br><span class="line">    <span class="function"><span class="keyword">virtual</span> <span class="keyword">void</span> <span class="title">B3_fun3</span><span class="params">()</span> </span>&#123; cout &lt;&lt; <span class="string">&quot;Base3::B3_fun3()&quot;</span> &lt;&lt; endl; &#125;</span><br><span class="line">&#125;;</span><br><span class="line"></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Derive</span> :</span> <span class="keyword">public</span> Base1, <span class="keyword">public</span> Base2, <span class="keyword">public</span> Base3</span><br><span class="line">&#123;</span><br><span class="line"><span class="keyword">public</span>:</span><br><span class="line">    <span class="function"><span class="keyword">virtual</span> <span class="keyword">void</span> <span class="title">D_fun1</span><span class="params">()</span> </span>&#123; cout &lt;&lt; <span class="string">&quot;Derive::D_fun1()&quot;</span> &lt;&lt; endl; &#125;</span><br><span class="line">    <span class="function"><span class="keyword">virtual</span> <span class="keyword">void</span> <span class="title">D_fun2</span><span class="params">()</span> </span>&#123; cout &lt;&lt; <span class="string">&quot;Derive::D_fun2()&quot;</span> &lt;&lt; endl; &#125;</span><br><span class="line">    <span class="function"><span class="keyword">virtual</span> <span class="keyword">void</span> <span class="title">D_fun3</span><span class="params">()</span> </span>&#123; cout &lt;&lt; <span class="string">&quot;Derive::D_fun3()&quot;</span> &lt;&lt; endl; &#125;</span><br><span class="line">&#125;;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">int</span> <span class="title">main</span><span class="params">()</span></span>&#123;</span><br><span class="line">    Base1 *p = <span class="keyword">new</span> <span class="built_in">Derive</span>();</span><br><span class="line">    p-&gt;<span class="built_in">B1_fun1</span>(); <span class="comment">// Base1::B1_fun1()</span></span><br><span class="line">    <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>基类和派生类的关系：</p>
<p><img src="https://pic.leetcode-cn.com/1612679879-DBSJce-image.png" alt="image.png"></p>
<p>派生类的虚函数表：（基类的顺序和声明的顺序一致）</p>
<p><img src="https://pic.leetcode-cn.com/1612682139-oQZazN-image.png" alt="image.png"></p>
</li>
<li>
<p>多继承有虚函数覆盖的情况：</p>
 <figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;iostream&gt;</span></span></span><br><span class="line"><span class="keyword">using</span> <span class="keyword">namespace</span> std;</span><br><span class="line"></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Base1</span></span></span><br><span class="line"><span class="class">&#123;</span></span><br><span class="line"><span class="keyword">public</span>:</span><br><span class="line">    <span class="function"><span class="keyword">virtual</span> <span class="keyword">void</span> <span class="title">fun1</span><span class="params">()</span> </span>&#123; cout &lt;&lt; <span class="string">&quot;Base1::fun1()&quot;</span> &lt;&lt; endl; &#125;</span><br><span class="line">    <span class="function"><span class="keyword">virtual</span> <span class="keyword">void</span> <span class="title">B1_fun2</span><span class="params">()</span> </span>&#123; cout &lt;&lt; <span class="string">&quot;Base1::B1_fun2()&quot;</span> &lt;&lt; endl; &#125;</span><br><span class="line">    <span class="function"><span class="keyword">virtual</span> <span class="keyword">void</span> <span class="title">B1_fun3</span><span class="params">()</span> </span>&#123; cout &lt;&lt; <span class="string">&quot;Base1::B1_fun3()&quot;</span> &lt;&lt; endl; &#125;</span><br><span class="line">&#125;;</span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Base2</span></span></span><br><span class="line"><span class="class">&#123;</span></span><br><span class="line"><span class="keyword">public</span>:</span><br><span class="line">    <span class="function"><span class="keyword">virtual</span> <span class="keyword">void</span> <span class="title">fun1</span><span class="params">()</span> </span>&#123; cout &lt;&lt; <span class="string">&quot;Base2::fun1()&quot;</span> &lt;&lt; endl; &#125;</span><br><span class="line">    <span class="function"><span class="keyword">virtual</span> <span class="keyword">void</span> <span class="title">B2_fun2</span><span class="params">()</span> </span>&#123; cout &lt;&lt; <span class="string">&quot;Base2::B2_fun2()&quot;</span> &lt;&lt; endl; &#125;</span><br><span class="line">    <span class="function"><span class="keyword">virtual</span> <span class="keyword">void</span> <span class="title">B2_fun3</span><span class="params">()</span> </span>&#123; cout &lt;&lt; <span class="string">&quot;Base2::B2_fun3()&quot;</span> &lt;&lt; endl; &#125;</span><br><span class="line">&#125;;</span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Base3</span></span></span><br><span class="line"><span class="class">&#123;</span></span><br><span class="line"><span class="keyword">public</span>:</span><br><span class="line">    <span class="function"><span class="keyword">virtual</span> <span class="keyword">void</span> <span class="title">fun1</span><span class="params">()</span> </span>&#123; cout &lt;&lt; <span class="string">&quot;Base3::fun1()&quot;</span> &lt;&lt; endl; &#125;</span><br><span class="line">    <span class="function"><span class="keyword">virtual</span> <span class="keyword">void</span> <span class="title">B3_fun2</span><span class="params">()</span> </span>&#123; cout &lt;&lt; <span class="string">&quot;Base3::B3_fun2()&quot;</span> &lt;&lt; endl; &#125;</span><br><span class="line">    <span class="function"><span class="keyword">virtual</span> <span class="keyword">void</span> <span class="title">B3_fun3</span><span class="params">()</span> </span>&#123; cout &lt;&lt; <span class="string">&quot;Base3::B3_fun3()&quot;</span> &lt;&lt; endl; &#125;</span><br><span class="line">&#125;;</span><br><span class="line"></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Derive</span> :</span> <span class="keyword">public</span> Base1, <span class="keyword">public</span> Base2, <span class="keyword">public</span> Base3</span><br><span class="line">&#123;</span><br><span class="line"><span class="keyword">public</span>:</span><br><span class="line">    <span class="function"><span class="keyword">virtual</span> <span class="keyword">void</span> <span class="title">fun1</span><span class="params">()</span> </span>&#123; cout &lt;&lt; <span class="string">&quot;Derive::fun1()&quot;</span> &lt;&lt; endl; &#125;</span><br><span class="line">    <span class="function"><span class="keyword">virtual</span> <span class="keyword">void</span> <span class="title">D_fun2</span><span class="params">()</span> </span>&#123; cout &lt;&lt; <span class="string">&quot;Derive::D_fun2()&quot;</span> &lt;&lt; endl; &#125;</span><br><span class="line">    <span class="function"><span class="keyword">virtual</span> <span class="keyword">void</span> <span class="title">D_fun3</span><span class="params">()</span> </span>&#123; cout &lt;&lt; <span class="string">&quot;Derive::D_fun3()&quot;</span> &lt;&lt; endl; &#125;</span><br><span class="line">&#125;;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">int</span> <span class="title">main</span><span class="params">()</span></span>&#123;</span><br><span class="line">    Base1 *p1 = <span class="keyword">new</span> <span class="built_in">Derive</span>();</span><br><span class="line">    Base2 *p2 = <span class="keyword">new</span> <span class="built_in">Derive</span>();</span><br><span class="line">    Base3 *p3 = <span class="keyword">new</span> <span class="built_in">Derive</span>();</span><br><span class="line">    p1-&gt;<span class="built_in">fun1</span>(); <span class="comment">// Derive::fun1()</span></span><br><span class="line">    p2-&gt;<span class="built_in">fun1</span>(); <span class="comment">// Derive::fun1()</span></span><br><span class="line">    p3-&gt;<span class="built_in">fun1</span>(); <span class="comment">// Derive::fun1()</span></span><br><span class="line">    <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>基类和派生类的关系：</p>
<p><img src="https://pic.leetcode-cn.com/1612681289-WjDonI-image.png" alt="image.png"></p>
<p>派生类的虚函数表：</p>
<p><img src="https://pic.leetcode-cn.com/1612682194-qhLdri-image.png" alt="image.png"></p>
</li>
</ol>
</li>
</ol>
<h2 id="5-如何禁止构造函数的使用"><a class="markdownIt-Anchor" href="#5-如何禁止构造函数的使用"></a> 5、如何禁止构造函数的使用？</h2>
<p>面试高频指数：两星</p>
<hr>
<p>为类的构造函数增加 <code>=delete</code> 修饰符，可以达到虽然声明了构造函数但禁止使用的目的。</p>
<figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;iostream&gt;</span></span></span><br><span class="line"></span><br><span class="line"><span class="keyword">using</span> <span class="keyword">namespace</span> std;</span><br><span class="line"></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">A</span> &#123;</span></span><br><span class="line"><span class="keyword">public</span>:</span><br><span class="line">    <span class="keyword">int</span> var1, var2;</span><br><span class="line">    <span class="built_in">A</span>()&#123;</span><br><span class="line">        var1 = <span class="number">10</span>;</span><br><span class="line">        var2 = <span class="number">20</span>;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="built_in">A</span>(<span class="keyword">int</span> tmp1, <span class="keyword">int</span> tmp2) = <span class="keyword">delete</span>;</span><br><span class="line">&#125;;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">int</span> <span class="title">main</span><span class="params">()</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">    A ex1;    </span><br><span class="line">    <span class="function">A <span class="title">ex2</span><span class="params">(<span class="number">12</span>,<span class="number">13</span>)</span></span>; <span class="comment">// error: use of deleted function &#x27;A::A(int, int)&#x27;</span></span><br><span class="line">    <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>说明：上述代码中，使用了已经删除 <code>delete</code> 的构造函数，程序出现错误。</p>
<h2 id="6-什么是类的默认构造函数"><a class="markdownIt-Anchor" href="#6-什么是类的默认构造函数"></a> 6、什么是类的默认构造函数？</h2>
<p>面试高频指数：三星</p>
<hr>
<p>默认构造函数：未提供任何实参，来控制默认初始化过程的构造函数称为默认构造函数。</p>
<figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;iostream&gt;</span></span></span><br><span class="line"></span><br><span class="line"><span class="keyword">using</span> <span class="keyword">namespace</span> std;</span><br><span class="line"></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">A</span></span></span><br><span class="line"><span class="class">&#123;</span></span><br><span class="line"><span class="keyword">public</span>:</span><br><span class="line">    <span class="built_in">A</span>()&#123; <span class="comment">// 类的默认构造函数</span></span><br><span class="line">        var = <span class="number">10</span>;</span><br><span class="line">        c = <span class="string">&#x27;q&#x27;</span>;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">int</span> var;</span><br><span class="line">    <span class="keyword">char</span> c;</span><br><span class="line">&#125;;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">int</span> <span class="title">main</span><span class="params">()</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">    A ex;</span><br><span class="line">    cout &lt;&lt; ex.c &lt;&lt; endl &lt;&lt; ex.var &lt;&lt; endl;</span><br><span class="line">    <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">&#125;</span><br><span class="line"><span class="comment">/*</span></span><br><span class="line"><span class="comment">运行结果：</span></span><br><span class="line"><span class="comment">q</span></span><br><span class="line"><span class="comment">10</span></span><br><span class="line"><span class="comment">*/</span></span><br></pre></td></tr></table></figure>
<p>说明：上述程序中定义变量 <code>ex</code> 时，未提供任何实参，程序运行时会调用默认的构造函数。</p>
<h2 id="7-构造函数-析构函数是否需要定义成虚函数为什么"><a class="markdownIt-Anchor" href="#7-构造函数-析构函数是否需要定义成虚函数为什么"></a> 7、构造函数、析构函数是否需要定义成虚函数？为什么？</h2>
<p>面试高频指数：四星</p>
<hr>
<p>构造函数一般不定义为虚函数，原因：</p>
<ul>
<li>从存储空间的角度考虑：构造函数是在实例化对象的时候进行调用，如果此时将构造函数定义成虚函数，需要通过访问该对象所在的内存空间才能进行虚函数的调用（因为需要通过指向虚函数表的指针调用虚函数表，虽然虚函数表在编译时就有了，但是没有虚函数的指针，虚函数的指针只有在创建了对象才有），但是此时该对象还未创建，便无法进行虚函数的调用。所以构造函数不能定义成虚函数。</li>
<li>从使用角度考虑：虚函数是基类的指针指向派生类的对象时，通过该指针实现对派生类的虚函数的调用，构造函数是在创建对象时自动调用的。</li>
<li>从实现上考虑：虚函数表是在创建对象之后才有的，因此不能定义成虚函数。</li>
<li>从类型上考虑：在创建对象时需要明确其类型。</li>
</ul>
<p>析构函数一般定义成虚函数，原因：</p>
<p>析构函数定义成虚函数是为了防止内存泄漏，因为当基类的指针或者引用指向或绑定到派生类的对象时，如果未将基类的析构函数定义成虚函数，会调用基类的析构函数，那么只能将基类的成员所占的空间释放掉，派生类中特有的就会无法释放内存空间导致内存泄漏。</p>
<h2 id="8-如何避免拷贝"><a class="markdownIt-Anchor" href="#8-如何避免拷贝"></a> 8、如何避免拷贝？</h2>
<p>面试高频指数：两星</p>
<hr>
<p>最直观的想法是：将类的拷贝构造函数和赋值构造函数声明为私有 <code>private</code>，但对于类的成员函数和友元函数依然可以调用，达不到完全禁止类的对象被拷贝的目的，而且程序会出现错误，因为未对函数进行定义。</p>
<p>解决方法：声明一个基类，具体做法如下：</p>
<ul>
<li>定义一个基类，将其中的拷贝构造函数和赋值构造函数声明为私有 <code>private</code></li>
<li>派生类以私有 <code>private</code> 的方式继承基类</li>
</ul>
<figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Uncopyable</span></span></span><br><span class="line"><span class="class">&#123;</span></span><br><span class="line"><span class="keyword">public</span>:</span><br><span class="line">    <span class="built_in">Uncopyable</span>() &#123;&#125;</span><br><span class="line">    ~<span class="built_in">Uncopyable</span>() &#123;&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">private</span>:</span><br><span class="line">    <span class="built_in">Uncopyable</span>(<span class="keyword">const</span> Uncopyable &amp;);            <span class="comment">// 拷贝构造函数</span></span><br><span class="line">    Uncopyable &amp;<span class="keyword">operator</span>=(<span class="keyword">const</span> Uncopyable &amp;); <span class="comment">// 赋值构造函数</span></span><br><span class="line">&#125;;</span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">A</span> :</span> <span class="keyword">private</span> Uncopyable <span class="comment">// 注意继承方式</span></span><br><span class="line">&#123; </span><br><span class="line">&#125;;</span><br></pre></td></tr></table></figure>
<p>简单解释：</p>
<ul>
<li>能够保证，在派生类 <code>A</code> 的成员函数和友元函数中无法进行拷贝操作，因为无法调用基类 <code>Uncopyable</code> 的拷贝构造函数或赋值构造函数。同样，在类的外部也无法进行拷贝操作。</li>
</ul>
<h2 id="9-如何减少构造函数开销"><a class="markdownIt-Anchor" href="#9-如何减少构造函数开销"></a> 9、如何减少构造函数开销？</h2>
<p>面试高频指数：两星</p>
<hr>
<p>在构造函数中使用类初始化列表，会减少调用默认的构造函数产生的开销，具体原因可以参考本章”为什么用成员初始化列表会快些“这个问题。</p>
<figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br></pre></td><td class="code"><pre><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">A</span></span></span><br><span class="line"><span class="class">&#123;</span></span><br><span class="line"><span class="keyword">private</span>:</span><br><span class="line">    <span class="keyword">int</span> val;</span><br><span class="line"><span class="keyword">public</span>:</span><br><span class="line">    <span class="built_in">A</span>()</span><br><span class="line">    &#123;</span><br><span class="line">        cout &lt;&lt; <span class="string">&quot;A()&quot;</span> &lt;&lt; endl;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="built_in">A</span>(<span class="keyword">int</span> tmp)</span><br><span class="line">    &#123;</span><br><span class="line">        val = tmp;</span><br><span class="line">        cout &lt;&lt; <span class="string">&quot;A(int &quot;</span> &lt;&lt; val &lt;&lt; <span class="string">&quot;)&quot;</span> &lt;&lt; endl;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;;</span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Test1</span></span></span><br><span class="line"><span class="class">&#123;</span></span><br><span class="line"><span class="keyword">private</span>:</span><br><span class="line">    A ex;</span><br><span class="line"></span><br><span class="line"><span class="keyword">public</span>:</span><br><span class="line">    <span class="built_in">Test1</span>() : <span class="built_in">ex</span>(<span class="number">1</span>) <span class="comment">// 成员列表初始化方式</span></span><br><span class="line">    &#123;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;;</span><br></pre></td></tr></table></figure>
<h2 id="10-多重继承时会出现什么状况如何解决"><a class="markdownIt-Anchor" href="#10-多重继承时会出现什么状况如何解决"></a> 10、多重继承时会出现什么状况？如何解决？</h2>
<p>面试高频指数：四星</p>
<hr>
<p>多重继承（多继承）：是指从多个直接基类中产生派生类。</p>
<p>多重继承容易出现的问题：命名冲突和数据冗余问题。</p>
<p>举例：</p>
<figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;iostream&gt;</span></span></span><br><span class="line"><span class="keyword">using</span> <span class="keyword">namespace</span> std;</span><br><span class="line"></span><br><span class="line"><span class="comment">// 间接基类</span></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Base1</span></span></span><br><span class="line"><span class="class">&#123;</span></span><br><span class="line"><span class="keyword">public</span>:</span><br><span class="line">    <span class="keyword">int</span> var1;</span><br><span class="line">&#125;;</span><br><span class="line"></span><br><span class="line"><span class="comment">// 直接基类</span></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Base2</span> :</span> <span class="keyword">public</span> Base1</span><br><span class="line">&#123;</span><br><span class="line"><span class="keyword">public</span>:</span><br><span class="line">    <span class="keyword">int</span> var2;</span><br><span class="line">&#125;;</span><br><span class="line"></span><br><span class="line"><span class="comment">// 直接基类</span></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Base3</span> :</span> <span class="keyword">public</span> Base1</span><br><span class="line">&#123;</span><br><span class="line"><span class="keyword">public</span>:</span><br><span class="line">    <span class="keyword">int</span> var3;</span><br><span class="line">&#125;;</span><br><span class="line"></span><br><span class="line"><span class="comment">// 派生类</span></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Derive</span> :</span> <span class="keyword">public</span> Base2, <span class="keyword">public</span> Base3</span><br><span class="line">&#123;</span><br><span class="line"><span class="keyword">public</span>:</span><br><span class="line">    <span class="function"><span class="keyword">void</span> <span class="title">set_var1</span><span class="params">(<span class="keyword">int</span> tmp)</span> </span>&#123; var1 = tmp; &#125; <span class="comment">// error: reference to &#x27;var1&#x27; is ambiguous. 命名冲突</span></span><br><span class="line">    <span class="function"><span class="keyword">void</span> <span class="title">set_var2</span><span class="params">(<span class="keyword">int</span> tmp)</span> </span>&#123; var2 = tmp; &#125;</span><br><span class="line">    <span class="function"><span class="keyword">void</span> <span class="title">set_var3</span><span class="params">(<span class="keyword">int</span> tmp)</span> </span>&#123; var3 = tmp; &#125;</span><br><span class="line">    <span class="function"><span class="keyword">void</span> <span class="title">set_var4</span><span class="params">(<span class="keyword">int</span> tmp)</span> </span>&#123; var4 = tmp; &#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">private</span>:</span><br><span class="line">    <span class="keyword">int</span> var4;</span><br><span class="line">&#125;;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">int</span> <span class="title">main</span><span class="params">()</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">    Derive d;</span><br><span class="line">    <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>上述程序的继承关系如下：（菱形继承）</p>
<p><img src="https://pic.leetcode-cn.com/1612681677-Jgekej-image.png" alt="image.png"></p>
<p><strong>上述代码中存在的问题：</strong></p>
<p>对于派生类 <code>Derive</code> 上述代码中存在直接继承关系和间接继承关系。</p>
<ul>
<li>直接继承：<code>Base2</code>、<code>Base3</code></li>
<li>间接继承：<code>Base1</code></li>
</ul>
<p>对与派生类中继承的成员变量 <code>var1</code>，从继承关系来看，实际上保存了两份，一份是来自基类 <code>Base2</code>，一份来自基类<code>Base3</code>。因此，出现了命名冲突。</p>
<p><strong>解决方法1：</strong> 声明出现冲突的成员变量来源于哪个类</p>
<figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;iostream&gt;</span></span></span><br><span class="line"><span class="keyword">using</span> <span class="keyword">namespace</span> std;</span><br><span class="line"></span><br><span class="line"><span class="comment">// 间接基类</span></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Base1</span></span></span><br><span class="line"><span class="class">&#123;</span></span><br><span class="line"><span class="keyword">public</span>:</span><br><span class="line">    <span class="keyword">int</span> var1;</span><br><span class="line">&#125;;</span><br><span class="line"></span><br><span class="line"><span class="comment">// 直接基类</span></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Base2</span> :</span> <span class="keyword">public</span> Base1</span><br><span class="line">&#123;</span><br><span class="line"><span class="keyword">public</span>:</span><br><span class="line">    <span class="keyword">int</span> var2;</span><br><span class="line">&#125;;</span><br><span class="line"></span><br><span class="line"><span class="comment">// 直接基类</span></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Base3</span> :</span> <span class="keyword">public</span> Base1</span><br><span class="line">&#123;</span><br><span class="line"><span class="keyword">public</span>:</span><br><span class="line">    <span class="keyword">int</span> var3;</span><br><span class="line">&#125;;</span><br><span class="line"></span><br><span class="line"><span class="comment">// 派生类 </span></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Derive</span> :</span> <span class="keyword">public</span> Base2, <span class="keyword">public</span> Base3</span><br><span class="line">&#123;</span><br><span class="line"><span class="keyword">public</span>:</span><br><span class="line">    <span class="function"><span class="keyword">void</span> <span class="title">set_var1</span><span class="params">(<span class="keyword">int</span> tmp)</span> </span>&#123; Base2::var1 = tmp; &#125; <span class="comment">// 这里声明成员变量来源于类 Base2，当然也可以声明来源于类 Base3</span></span><br><span class="line">    <span class="function"><span class="keyword">void</span> <span class="title">set_var2</span><span class="params">(<span class="keyword">int</span> tmp)</span> </span>&#123; var2 = tmp; &#125;</span><br><span class="line">    <span class="function"><span class="keyword">void</span> <span class="title">set_var3</span><span class="params">(<span class="keyword">int</span> tmp)</span> </span>&#123; var3 = tmp; &#125;</span><br><span class="line">    <span class="function"><span class="keyword">void</span> <span class="title">set_var4</span><span class="params">(<span class="keyword">int</span> tmp)</span> </span>&#123; var4 = tmp; &#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">private</span>:</span><br><span class="line">    <span class="keyword">int</span> var4;</span><br><span class="line">&#125;;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">int</span> <span class="title">main</span><span class="params">()</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">    Derive d;</span><br><span class="line">    <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p><strong>解决办法2：虚继承</strong></p>
<p>使用虚继承的目的：保证存在命名冲突的成员变量在派生类中只保留一份，即使间接基类中的成员在派生类中只保留一份。在菱形继承关系中，间接基类称为虚基类，直接基类和间接基类之间的继承关系称为虚继承。</p>
<p>实现方式：在继承方式前面加上 <code>virtual</code> 关键字。</p>
<figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;iostream&gt;</span></span></span><br><span class="line"><span class="keyword">using</span> <span class="keyword">namespace</span> std;</span><br><span class="line"></span><br><span class="line"><span class="comment">// 间接基类，即虚基类</span></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Base1</span></span></span><br><span class="line"><span class="class">&#123;</span></span><br><span class="line"><span class="keyword">public</span>:</span><br><span class="line">    <span class="keyword">int</span> var1;</span><br><span class="line">&#125;;</span><br><span class="line"></span><br><span class="line"><span class="comment">// 直接基类 </span></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Base2</span> :</span> <span class="keyword">virtual</span> <span class="keyword">public</span> Base1 <span class="comment">// 虚继承</span></span><br><span class="line">&#123;</span><br><span class="line"><span class="keyword">public</span>:</span><br><span class="line">    <span class="keyword">int</span> var2;</span><br><span class="line">&#125;;</span><br><span class="line"></span><br><span class="line"><span class="comment">// 直接基类 </span></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Base3</span> :</span> <span class="keyword">virtual</span> <span class="keyword">public</span> Base1 <span class="comment">// 虚继承</span></span><br><span class="line">&#123;</span><br><span class="line"><span class="keyword">public</span>:</span><br><span class="line">    <span class="keyword">int</span> var3;</span><br><span class="line">&#125;;</span><br><span class="line"></span><br><span class="line"><span class="comment">// 派生类</span></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Derive</span> :</span> <span class="keyword">public</span> Base2, <span class="keyword">public</span> Base3</span><br><span class="line">&#123;</span><br><span class="line"><span class="keyword">public</span>:</span><br><span class="line">    <span class="function"><span class="keyword">void</span> <span class="title">set_var1</span><span class="params">(<span class="keyword">int</span> tmp)</span> </span>&#123; var1 = tmp; &#125; </span><br><span class="line">    <span class="function"><span class="keyword">void</span> <span class="title">set_var2</span><span class="params">(<span class="keyword">int</span> tmp)</span> </span>&#123; var2 = tmp; &#125;</span><br><span class="line">    <span class="function"><span class="keyword">void</span> <span class="title">set_var3</span><span class="params">(<span class="keyword">int</span> tmp)</span> </span>&#123; var3 = tmp; &#125;</span><br><span class="line">    <span class="function"><span class="keyword">void</span> <span class="title">set_var4</span><span class="params">(<span class="keyword">int</span> tmp)</span> </span>&#123; var4 = tmp; &#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">private</span>:</span><br><span class="line">    <span class="keyword">int</span> var4;</span><br><span class="line">&#125;;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">int</span> <span class="title">main</span><span class="params">()</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">    Derive d;</span><br><span class="line">    <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>类之间的继承关系：</p>
<p><img src="https://pic.leetcode-cn.com/1612681729-IhAKvb-image.png" alt="image.png"></p>
<h2 id="11-空类占多少字节c编译器会给一个空类自动生成哪些函数"><a class="markdownIt-Anchor" href="#11-空类占多少字节c编译器会给一个空类自动生成哪些函数"></a> 11、空类占多少字节？C++编译器会给一个空类自动生成哪些函数？</h2>
<p>面试高频指数：三星</p>
<hr>
<p><strong>空类声明时编译器不会生成任何成员函数：</strong></p>
<p>对于空类，声明编译器不会生成任何的成员函数，只会生成 1 个字节的占位符。</p>
<figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;iostream&gt;</span></span></span><br><span class="line"><span class="keyword">using</span> <span class="keyword">namespace</span> std;</span><br><span class="line"></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">A</span></span></span><br><span class="line"><span class="class">&#123;</span></span><br><span class="line">&#125;;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">int</span> <span class="title">main</span><span class="params">()</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">    cout &lt;&lt; <span class="string">&quot;sizeof(A):&quot;</span> &lt;&lt; <span class="built_in"><span class="keyword">sizeof</span></span>(A) &lt;&lt; endl; <span class="comment">// sizeof(A):1</span></span><br><span class="line">    <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p><strong>空类定义时编译器会生成 6 个成员函数：</strong></p>
<p>当空类 <code>A</code> 定义对象时，<code>sizeof(A)</code> 仍是为 1，但编译器会生成 6 个成员函数：缺省的构造函数、拷贝构造函数、析构函数、赋值运算符、两个取址运算符。</p>
<figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;iostream&gt;</span></span></span><br><span class="line"><span class="keyword">using</span> <span class="keyword">namespace</span> std;</span><br><span class="line"><span class="comment">/*</span></span><br><span class="line"><span class="comment">class A</span></span><br><span class="line"><span class="comment">&#123;&#125;; 该空类的等价写法如下：</span></span><br><span class="line"><span class="comment">*/</span></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">A</span></span></span><br><span class="line"><span class="class">&#123;</span></span><br><span class="line"><span class="keyword">public</span>:</span><br><span class="line">    <span class="built_in">A</span>()&#123;&#125;;                                       <span class="comment">// 缺省构造函数</span></span><br><span class="line">    <span class="built_in">A</span>(<span class="keyword">const</span> A &amp;tmp)&#123;&#125;;                           <span class="comment">// 拷贝构造函数</span></span><br><span class="line">    ~<span class="built_in">A</span>()&#123;&#125;;                                      <span class="comment">// 析构函数</span></span><br><span class="line">    A &amp;<span class="keyword">operator</span>=(<span class="keyword">const</span> A &amp;tmp)&#123;&#125;;                <span class="comment">// 赋值运算符</span></span><br><span class="line">    A *<span class="keyword">operator</span>&amp;() &#123; <span class="keyword">return</span> <span class="keyword">this</span>; &#125;;             <span class="comment">// 取址运算符</span></span><br><span class="line">    <span class="keyword">const</span> A *<span class="keyword">operator</span>&amp;() <span class="keyword">const</span> &#123; <span class="keyword">return</span> <span class="keyword">this</span>; &#125;; <span class="comment">// 取址运算符（const 版本）</span></span><br><span class="line">&#125;;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">int</span> <span class="title">main</span><span class="params">()</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">    A *p = <span class="keyword">new</span> <span class="built_in">A</span>(); </span><br><span class="line">    cout &lt;&lt; <span class="string">&quot;sizeof(A):&quot;</span> &lt;&lt; <span class="built_in"><span class="keyword">sizeof</span></span>(A) &lt;&lt; endl; <span class="comment">// sizeof(A):1</span></span><br><span class="line">    <span class="keyword">delete</span> p;       </span><br><span class="line">    <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<h2 id="12-为什么拷贝构造函数必须为引用"><a class="markdownIt-Anchor" href="#12-为什么拷贝构造函数必须为引用"></a> 12、为什么拷贝构造函数必须为引用？</h2>
<p>面试高频指数：两星</p>
<hr>
<p>原因：避免拷贝构造函数无限制地递归，最终导致栈溢出。</p>
<p>举例说明：</p>
<figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;iostream&gt;</span></span></span><br><span class="line"><span class="keyword">using</span> <span class="keyword">namespace</span> std;</span><br><span class="line"></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">A</span></span></span><br><span class="line"><span class="class">&#123;</span></span><br><span class="line"><span class="keyword">private</span>:</span><br><span class="line">    <span class="keyword">int</span> val;</span><br><span class="line"></span><br><span class="line"><span class="keyword">public</span>:</span><br><span class="line">    <span class="built_in">A</span>(<span class="keyword">int</span> tmp) : <span class="built_in">val</span>(tmp) <span class="comment">// 带参数构造函数</span></span><br><span class="line">    &#123;</span><br><span class="line">        cout &lt;&lt; <span class="string">&quot;A(int tmp)&quot;</span> &lt;&lt; endl;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="built_in">A</span>(<span class="keyword">const</span> A &amp;tmp) <span class="comment">// 拷贝构造函数</span></span><br><span class="line">    &#123;</span><br><span class="line">        cout &lt;&lt; <span class="string">&quot;A(const A &amp;tmp)&quot;</span> &lt;&lt; endl;</span><br><span class="line">        val = tmp.val;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    A &amp;<span class="keyword">operator</span>=(<span class="keyword">const</span> A &amp;tmp) <span class="comment">// 赋值函数（赋值运算符重载）</span></span><br><span class="line">    &#123;</span><br><span class="line">        cout &lt;&lt; <span class="string">&quot;A &amp;operator=(const A &amp;tmp)&quot;</span> &lt;&lt; endl;</span><br><span class="line">        val = tmp.val;</span><br><span class="line">        <span class="keyword">return</span> *<span class="keyword">this</span>;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">void</span> <span class="title">fun</span><span class="params">(A tmp)</span></span></span><br><span class="line"><span class="function">    </span>&#123;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">int</span> <span class="title">main</span><span class="params">()</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">    <span class="function">A <span class="title">ex1</span><span class="params">(<span class="number">1</span>)</span></span>;</span><br><span class="line">    <span class="function">A <span class="title">ex2</span><span class="params">(<span class="number">2</span>)</span></span>;</span><br><span class="line">    A ex3 = ex1;</span><br><span class="line">    ex2 = ex1;</span><br><span class="line">    ex2.<span class="built_in">fun</span>(ex1);</span><br><span class="line">    <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">&#125;</span><br><span class="line"><span class="comment">/*</span></span><br><span class="line"><span class="comment">运行结果：</span></span><br><span class="line"><span class="comment">A(int tmp)</span></span><br><span class="line"><span class="comment">A(int tmp)</span></span><br><span class="line"><span class="comment">A(const A &amp;tmp)</span></span><br><span class="line"><span class="comment">A &amp;operator=(const A &amp;tmp)</span></span><br><span class="line"><span class="comment">A(const A &amp;tmp)</span></span><br><span class="line"><span class="comment">*/</span></span><br></pre></td></tr></table></figure>
<ul>
<li>
<p>说明1：<code>ex2 = ex1;</code> 和 <code>A ex3 = ex1;</code> 为什么调用的函数不一样？</p>
<p>对象 <code>ex2</code> 已经实例化了，不需要构造，此时只是将 <code>ex1</code> 赋值给 <code>ex2</code>，只会调用赋值函数；但是 <code>ex3</code> 还没有实例化，因此调用的是拷贝构造函数，构造出 <code>ex3</code>，而不是赋值函数，这里涉及到构造函数的隐式调用。</p>
</li>
<li>
<p>说明2：如果拷贝构造函数中形参不是引用类型，<code>A ex3 = ex1;</code> 会出现什么问题？</p>
<p>构造 <code>ex3</code>，实质上是 <code>ex3.A(ex1);</code> ，假如拷贝构造函数参数不是引用类型，那么将使得 <code>ex3.A(ex1);</code> 相当于 <code>ex1</code> 作为函数 <code>A(const A tmp)</code> 的形参，在参数传递时相当于<code>A tmp = ex1;</code>，因为 <code>tmp</code> 没有被初始化，所以在 <code>A tmp = ex1</code> 中继续调用拷贝构造函数，接下来的是构造 <code>tmp</code>，也就是 <code>tmp.A(ex1)</code>，必然又会有 <code>ex1</code> 作为函数 <code>A(const A tmp);</code> 的形参，在参数传递时相当于即 <code>A tmp = ex1</code>，那么又会触发拷贝构造函数，就这样永远地递归下去。</p>
</li>
<li>
<p>说明3：为什么 <code>ex2.fun(ex1);</code> 会调用拷贝构造函数？</p>
<p><code>ex1</code> 作为参数传递给 <code>fun</code> 函数，即 <code>A tmp = ex1;</code>，这个过程会调用拷贝构造函数进行初始化。</p>
</li>
</ul>
<h2 id="13-c-类对象的初始化顺序"><a class="markdownIt-Anchor" href="#13-c-类对象的初始化顺序"></a> 13、C++ 类对象的初始化顺序</h2>
<p>面试高频指数：三星</p>
<hr>
<p>构造函数调用顺序：</p>
<ul>
<li>按照派生类继承基类的顺序，即派生列表中声明的顺序，依次调用基类的构造函数；</li>
<li>按照派生类中成员变量的声明顺序，依次调用派生类中成员变量所属类的构造函数；</li>
<li>执行派生类自身的构造函数。</li>
</ul>
<p>综上可以得出，类对象的初始化顺序：基类构造函数-&gt;派生类成员变量的构造函数-&gt;自身构造函数</p>
<p>注：</p>
<ul>
<li>基类构造函数的调用顺序与派生类的派生列表中的顺序有关；</li>
<li>成员变量的初始化顺序与声明顺序有关；</li>
<li>析构顺序和构造顺序相反。</li>
</ul>
<figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;iostream&gt;</span></span></span><br><span class="line"><span class="keyword">using</span> <span class="keyword">namespace</span> std;</span><br><span class="line"></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">A</span></span></span><br><span class="line"><span class="class">&#123;</span></span><br><span class="line"><span class="keyword">public</span>:</span><br><span class="line">    <span class="built_in">A</span>() &#123; cout &lt;&lt; <span class="string">&quot;A()&quot;</span> &lt;&lt; endl; &#125;</span><br><span class="line">    ~<span class="built_in">A</span>() &#123; cout &lt;&lt; <span class="string">&quot;~A()&quot;</span> &lt;&lt; endl; &#125;</span><br><span class="line">&#125;;</span><br><span class="line"></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">B</span></span></span><br><span class="line"><span class="class">&#123;</span></span><br><span class="line"><span class="keyword">public</span>:</span><br><span class="line">    <span class="built_in">B</span>() &#123; cout &lt;&lt; <span class="string">&quot;B()&quot;</span> &lt;&lt; endl; &#125;</span><br><span class="line">    ~<span class="built_in">B</span>() &#123; cout &lt;&lt; <span class="string">&quot;~B()&quot;</span> &lt;&lt; endl; &#125;</span><br><span class="line">&#125;;</span><br><span class="line"></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Test</span> :</span> <span class="keyword">public</span> A, <span class="keyword">public</span> B <span class="comment">// 派生列表</span></span><br><span class="line">&#123;</span><br><span class="line"><span class="keyword">public</span>:</span><br><span class="line">    <span class="built_in">Test</span>() &#123; cout &lt;&lt; <span class="string">&quot;Test()&quot;</span> &lt;&lt; endl; &#125;</span><br><span class="line">    ~<span class="built_in">Test</span>() &#123; cout &lt;&lt; <span class="string">&quot;~Test()&quot;</span> &lt;&lt; endl; &#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">private</span>:</span><br><span class="line">    B ex1;</span><br><span class="line">    A ex2;</span><br><span class="line">&#125;;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">int</span> <span class="title">main</span><span class="params">()</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">    Test ex;</span><br><span class="line">    <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">&#125;</span><br><span class="line"><span class="comment">/*</span></span><br><span class="line"><span class="comment">运行结果：</span></span><br><span class="line"><span class="comment">A()</span></span><br><span class="line"><span class="comment">B()</span></span><br><span class="line"><span class="comment">B()</span></span><br><span class="line"><span class="comment">A()</span></span><br><span class="line"><span class="comment">Test()</span></span><br><span class="line"><span class="comment">~Test()</span></span><br><span class="line"><span class="comment">~A()</span></span><br><span class="line"><span class="comment">~B()</span></span><br><span class="line"><span class="comment">~B()</span></span><br><span class="line"><span class="comment">~A()</span></span><br><span class="line"><span class="comment">*/</span></span><br></pre></td></tr></table></figure>
<p>程序运行结果分析：</p>
<ul>
<li>首先调用基类 A 和 B 的构造函数，按照派生列表 <code>public A, public B</code> 的顺序构造；</li>
<li>然后调用派生类 Test 的成员变量 ex1 和 ex2 的构造函数，按照派生类中成员变量声明的顺序构造；</li>
<li>最后调用派生类的构造函数；</li>
<li>接下来调用析构函数，和构造函数调用的顺序相反。</li>
</ul>
<h2 id="14-如何禁止一个类被实例化"><a class="markdownIt-Anchor" href="#14-如何禁止一个类被实例化"></a> 14、如何禁止一个类被实例化？</h2>
<p>面试高频指数：两星</p>
<hr>
<p>方法一：</p>
<ul>
<li>在类中定义一个纯虚函数，使该类成为抽象基类，因为不能创建抽象基类的实例化对象。</li>
</ul>
<figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;iostream&gt;</span></span></span><br><span class="line"></span><br><span class="line"><span class="keyword">using</span> <span class="keyword">namespace</span> std;</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">A</span> &#123;</span></span><br><span class="line"><span class="keyword">public</span>:</span><br><span class="line">    <span class="keyword">int</span> var1, var2;</span><br><span class="line">    <span class="built_in">A</span>()&#123;</span><br><span class="line">        var1 = <span class="number">10</span>;</span><br><span class="line">        var2 = <span class="number">20</span>;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="function"><span class="keyword">virtual</span> <span class="keyword">void</span> <span class="title">fun</span><span class="params">()</span> </span>= <span class="number">0</span>; <span class="comment">// 纯虚函数</span></span><br><span class="line">&#125;;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">int</span> <span class="title">main</span><span class="params">()</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">    A ex1; <span class="comment">// error: cannot declare variable &#x27;ex1&#x27; to be of abstract type &#x27;A&#x27;</span></span><br><span class="line">    <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>方法二：</p>
<ul>
<li>将类的构造函数声明为私有 <code>private</code></li>
</ul>
<h2 id="15-为什么用成员初始化列表会快一些"><a class="markdownIt-Anchor" href="#15-为什么用成员初始化列表会快一些"></a> 15、为什么用成员初始化列表会快一些？</h2>
<p>面试高频指数：三星</p>
<hr>
<p><strong>说明：</strong> 数据类型可分为内置类型和用户自定义类型（类类型），对于用户自定义类型，利用成员初始化列表效率高。</p>
<p><strong>原因：</strong> 用户自定义类型如果使用类初始化列表，直接调用该成员变量对应的构造函数即完成初始化；如果在构造函数中初始化，因为 C++ 规定，对象的成员变量的初始化动作发生在进入构造函数本体之前，那么在执行构造函数的函数体之前首先调用默认的构造函数为成员变量设初值，在进入函数体之后，调用该成员变量对应的构造函数。因此，使用列表初始化会减少调用默认的构造函数的过程，效率高。</p>
<figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;iostream&gt;</span></span></span><br><span class="line"><span class="keyword">using</span> <span class="keyword">namespace</span> std;</span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">A</span></span></span><br><span class="line"><span class="class">&#123;</span></span><br><span class="line"><span class="keyword">private</span>:</span><br><span class="line">    <span class="keyword">int</span> val;</span><br><span class="line"><span class="keyword">public</span>:</span><br><span class="line">    <span class="built_in">A</span>()</span><br><span class="line">    &#123;</span><br><span class="line">        cout &lt;&lt; <span class="string">&quot;A()&quot;</span> &lt;&lt; endl;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="built_in">A</span>(<span class="keyword">int</span> tmp)</span><br><span class="line">    &#123;</span><br><span class="line">        val = tmp;</span><br><span class="line">        cout &lt;&lt; <span class="string">&quot;A(int &quot;</span> &lt;&lt; val &lt;&lt; <span class="string">&quot;)&quot;</span> &lt;&lt; endl;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;;</span><br><span class="line"></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Test1</span></span></span><br><span class="line"><span class="class">&#123;</span></span><br><span class="line"><span class="keyword">private</span>:</span><br><span class="line">    A ex;</span><br><span class="line"></span><br><span class="line"><span class="keyword">public</span>:</span><br><span class="line">    <span class="built_in">Test1</span>() : <span class="built_in">ex</span>(<span class="number">1</span>) <span class="comment">// 成员列表初始化方式</span></span><br><span class="line">    &#123;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;;</span><br><span class="line"></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Test2</span></span></span><br><span class="line"><span class="class">&#123;</span></span><br><span class="line"><span class="keyword">private</span>:</span><br><span class="line">    A ex;</span><br><span class="line"></span><br><span class="line"><span class="keyword">public</span>:</span><br><span class="line">    <span class="built_in">Test2</span>() <span class="comment">// 函数体中赋值的方式</span></span><br><span class="line">    &#123;</span><br><span class="line">        ex = <span class="built_in">A</span>(<span class="number">2</span>);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;;</span><br><span class="line"><span class="function"><span class="keyword">int</span> <span class="title">main</span><span class="params">()</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">    Test1 ex1;</span><br><span class="line">    cout &lt;&lt; endl;</span><br><span class="line">    Test2 ex2;</span><br><span class="line">    <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">&#125;</span><br><span class="line"><span class="comment">/*</span></span><br><span class="line"><span class="comment">运行结果：</span></span><br><span class="line"><span class="comment">A(int 1)</span></span><br><span class="line"><span class="comment"></span></span><br><span class="line"><span class="comment">A()</span></span><br><span class="line"><span class="comment">A(int 2)</span></span><br><span class="line"><span class="comment">*/</span></span><br></pre></td></tr></table></figure>
<p>说明：从程序运行结果可以看出，使用成员列表初始化的方式会省去调用默认的构造函数的过程。</p>
<h2 id="16-实例化一个对象需要哪几个阶段"><a class="markdownIt-Anchor" href="#16-实例化一个对象需要哪几个阶段"></a> 16、实例化一个对象需要哪几个阶段</h2>
<p>面试高频指数：三星</p>
<hr>
<ol>
<li>
<p>分配空间</p>
<p>创建类对象首先要为该对象分配内存空间。不同的对象，为其分配空间的时机未必相同。全局对象、静态对象、分配在栈区域的对象，在编译阶段进行内存分配；存储在堆空间的对象，是在运行阶段进行内存分配。</p>
</li>
<li>
<p>初始化</p>
<p>首先明确一点：初始化不同于赋值。初始化发生在赋值之前，初始化随对象的创建而进行，而赋值是在对象创建好后，为其赋上相应的值。这一点可以联想下上一个问题中提到：初始化列表先于构造函数体内的代码执行，初始化列表执行的是数据成员的初始化过程，这个可以从成员对象的构造函数被调用看得出来。</p>
</li>
<li>
<p>赋值</p>
<p>对象初始化完成后，可以对其进行赋值。对于一个类的对象，其成员变量的赋值过程发生在类的构造函数的函数体中。当执行完该函数体，也就意味着类对象的实例化过程完成了。（总结：构造函数实现了对象的初始化和赋值两个过程，对象的初始化是通过初始化列表来完成，而对象的赋值则才是通过构造函数的函数体来实现。）</p>
</li>
</ol>
<p>注：对于拥有虚函数的类的对象，还需要给虚表指针赋值。</p>
<ul>
<li>没有继承关系的类，分配完内存后，首先给虚表指针赋值，然后再列表初始化以及执行构造函数的函数体，即上述中的初始化和赋值操作。</li>
<li>有继承关系的类，分配内存之后，首先进行基类的构造过程，然后给该派生类的虚表指针赋值，最后再列表初始化以及执行构造函数的函数体，即上述中的初始化和赋值操作。</li>
</ul>
<h2 id="17-友元函数的作用及使用场景"><a class="markdownIt-Anchor" href="#17-友元函数的作用及使用场景"></a> 17、友元函数的作用及使用场景</h2>
<p>面试高频指数：两星</p>
<hr>
<p>作用：友元提供了不同类的成员函数之间、类的成员函数与一般函数之间进行数据共享的机制。通过友元，一个普通函数或另一个类中的成员函数可以访问类中的私有成员和保护成员。</p>
<p>使用场景：</p>
<ol>
<li>
<p>普通函数定义为友元函数，使普通函数能够访问类的私有成员。</p>
 <figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;iostream&gt;</span></span></span><br><span class="line"></span><br><span class="line"><span class="keyword">using</span> <span class="keyword">namespace</span> std;</span><br><span class="line"></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">A</span></span></span><br><span class="line"><span class="class">&#123;</span></span><br><span class="line">    <span class="keyword">friend</span> ostream &amp;<span class="keyword">operator</span>&lt;&lt;(ostream &amp;_cout, <span class="keyword">const</span> A &amp;tmp); <span class="comment">// 声明为类的友元函数</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">public</span>:</span><br><span class="line">    <span class="built_in">A</span>(<span class="keyword">int</span> tmp) : <span class="built_in">var</span>(tmp)</span><br><span class="line">    &#123;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">private</span>:</span><br><span class="line">    <span class="keyword">int</span> var;</span><br><span class="line">&#125;;</span><br><span class="line"></span><br><span class="line">ostream &amp;<span class="keyword">operator</span>&lt;&lt;(ostream &amp;_cout, <span class="keyword">const</span> A &amp;tmp)</span><br><span class="line">&#123;</span><br><span class="line">    _cout &lt;&lt; tmp.var;</span><br><span class="line">    <span class="keyword">return</span> _cout;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">int</span> <span class="title">main</span><span class="params">()</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">    <span class="function">A <span class="title">ex</span><span class="params">(<span class="number">4</span>)</span></span>;</span><br><span class="line">    cout &lt;&lt; ex &lt;&lt; endl; <span class="comment">// 4</span></span><br><span class="line">    <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
</li>
<li>
<p>友元类：类之间共享数据。</p>
 <figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;iostream&gt;</span></span></span><br><span class="line"></span><br><span class="line"><span class="keyword">using</span> <span class="keyword">namespace</span> std;</span><br><span class="line"></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">A</span></span></span><br><span class="line"><span class="class">&#123;</span></span><br><span class="line">    <span class="keyword">friend</span> <span class="class"><span class="keyword">class</span> <span class="title">B</span>;</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">public</span>:</span><br><span class="line">    <span class="built_in">A</span>() : <span class="built_in">var</span>(<span class="number">10</span>)&#123;&#125;</span><br><span class="line">    <span class="built_in">A</span>(<span class="keyword">int</span> tmp) : <span class="built_in">var</span>(tmp) &#123;&#125;</span><br><span class="line">    <span class="function"><span class="keyword">void</span> <span class="title">fun</span><span class="params">()</span></span></span><br><span class="line"><span class="function">    </span>&#123;</span><br><span class="line">        cout &lt;&lt; <span class="string">&quot;fun():&quot;</span> &lt;&lt; var &lt;&lt; endl;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">private</span>:</span><br><span class="line">    <span class="keyword">int</span> var;</span><br><span class="line">&#125;;</span><br><span class="line"></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">B</span></span></span><br><span class="line"><span class="class">&#123;</span></span><br><span class="line"><span class="keyword">public</span>:</span><br><span class="line">    <span class="built_in">B</span>() &#123;&#125;</span><br><span class="line">    <span class="function"><span class="keyword">void</span> <span class="title">fun</span><span class="params">()</span></span></span><br><span class="line"><span class="function">    </span>&#123;</span><br><span class="line">        cout &lt;&lt; <span class="string">&quot;fun():&quot;</span> &lt;&lt; ex.var &lt;&lt; endl; <span class="comment">// 访问类 A 中的私有成员</span></span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">private</span>:</span><br><span class="line">    A ex;</span><br><span class="line">&#125;;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">int</span> <span class="title">main</span><span class="params">()</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">    B ex;</span><br><span class="line">    ex.<span class="built_in">fun</span>(); <span class="comment">// fun():10</span></span><br><span class="line">    <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
</li>
</ol>
<h2 id="18-静态绑定和动态绑定是怎么实现的"><a class="markdownIt-Anchor" href="#18-静态绑定和动态绑定是怎么实现的"></a> 18、静态绑定和动态绑定是怎么实现的？</h2>
<p>面试高频指数：三星</p>
<hr>
<p>静态类型和动态类型：</p>
<ul>
<li>静态类型：变量在声明时的类型，是在编译阶段确定的。静态类型不能更改。</li>
<li>动态类型：目前所指对象的类型，是在运行阶段确定的。动态类型可以更改。</li>
</ul>
<p>静态绑定和动态绑定：</p>
<ul>
<li>静态绑定是指程序在 <em>编译阶段</em> 确定对象的类型（静态类型）。</li>
<li>动态绑定是指程序在 <em>运行阶段</em> 确定对象的类型（动态类型）。</li>
</ul>
<p>静态绑定和动态绑定的区别：</p>
<ul>
<li>发生的时期不同：如上。</li>
<li>对象的静态类型不能更改，动态类型可以更改。</li>
</ul>
<p>注：对于类的成员函数，只有虚函数是动态绑定，其他都是静态绑定。</p>
<figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;iostream&gt;</span></span></span><br><span class="line"></span><br><span class="line"><span class="keyword">using</span> <span class="keyword">namespace</span> std;</span><br><span class="line"></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Base</span></span></span><br><span class="line"><span class="class">&#123;</span></span><br><span class="line"><span class="keyword">public</span>:</span><br><span class="line">	<span class="function"><span class="keyword">virtual</span> <span class="keyword">void</span> <span class="title">fun</span><span class="params">()</span> </span>&#123; cout &lt;&lt; <span class="string">&quot;Base::fun()&quot;</span> &lt;&lt; endl;</span><br><span class="line">     &#125;</span><br><span class="line">&#125;;</span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Derive</span> :</span> <span class="keyword">public</span> Base</span><br><span class="line">&#123;</span><br><span class="line"><span class="keyword">public</span>:</span><br><span class="line">	<span class="function"><span class="keyword">void</span> <span class="title">fun</span><span class="params">()</span> </span>&#123; cout &lt;&lt; <span class="string">&quot;Derive::fun()&quot;</span>; </span><br><span class="line">    &#125;</span><br><span class="line">&#125;;</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">int</span> <span class="title">main</span><span class="params">()</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">	Base *p = <span class="keyword">new</span> <span class="built_in">Derive</span>(); <span class="comment">// p 的静态类型是 Base*，动态类型是 Derive*</span></span><br><span class="line">    p-&gt;<span class="built_in">fun</span>(); <span class="comment">// fun 是虚函数，运行阶段进行动态绑定</span></span><br><span class="line">	<span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">&#125;</span><br><span class="line"><span class="comment">/*</span></span><br><span class="line"><span class="comment">运行结果：</span></span><br><span class="line"><span class="comment">Derive::fun()</span></span><br><span class="line"><span class="comment">*/</span></span><br></pre></td></tr></table></figure>
<h2 id="19-深拷贝和浅拷贝的区别"><a class="markdownIt-Anchor" href="#19-深拷贝和浅拷贝的区别"></a> 19、深拷贝和浅拷贝的区别</h2>
<p>面试高频指数：五星</p>
<hr>
<p>如果一个类拥有资源，该类的对象进行复制时，如果资源重新分配，就是深拷贝， 否则就是浅拷贝。</p>
<ul>
<li>深拷贝：该对象和原对象占用不同的内存空间，既拷贝存储在栈空间的内容，又拷贝存储在堆空间中的内容。</li>
<li>浅拷贝：该对象和原对象占用同一块内存空间，仅拷贝类中位于栈空间中的内容。</li>
</ul>
<p>当类的成员变量中有指针变量时，最好使用深拷贝。因为当两个对象指向同一块内存空间，如果使用浅拷贝，当其中一个对象的删除后，该快内存空间就会被释放，另外一个对象指向的就是垃圾内存。</p>
<p><strong>浅拷贝实例</strong></p>
<figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;iostream&gt;</span></span></span><br><span class="line"></span><br><span class="line"><span class="keyword">using</span> <span class="keyword">namespace</span> std;</span><br><span class="line"></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Test</span></span></span><br><span class="line"><span class="class">&#123;</span></span><br><span class="line"><span class="keyword">private</span>:</span><br><span class="line">	<span class="keyword">int</span> *p;</span><br><span class="line"></span><br><span class="line"><span class="keyword">public</span>:</span><br><span class="line">	<span class="built_in">Test</span>(<span class="keyword">int</span> tmp)</span><br><span class="line">	&#123;</span><br><span class="line">		<span class="keyword">this</span>-&gt;p = <span class="keyword">new</span> <span class="built_in"><span class="keyword">int</span></span>(tmp);</span><br><span class="line">		cout &lt;&lt; <span class="string">&quot;Test(int tmp)&quot;</span> &lt;&lt; endl;</span><br><span class="line">	&#125;</span><br><span class="line">	~<span class="built_in">Test</span>()</span><br><span class="line">	&#123;</span><br><span class="line">		<span class="keyword">if</span> (p != <span class="literal">NULL</span>)</span><br><span class="line">		&#123;</span><br><span class="line">			<span class="keyword">delete</span> p;</span><br><span class="line">		&#125;</span><br><span class="line">		cout &lt;&lt; <span class="string">&quot;~Test()&quot;</span> &lt;&lt; endl;</span><br><span class="line">	&#125;</span><br><span class="line">&#125;;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">int</span> <span class="title">main</span><span class="params">()</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">	<span class="function">Test <span class="title">ex1</span><span class="params">(<span class="number">10</span>)</span></span>;	</span><br><span class="line">	Test ex2 = ex1; </span><br><span class="line">	<span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">&#125;</span><br><span class="line"><span class="comment">/*</span></span><br><span class="line"><span class="comment">运行结果：</span></span><br><span class="line"><span class="comment">Test(int tmp)</span></span><br><span class="line"><span class="comment">~Test()</span></span><br><span class="line"><span class="comment">*/</span></span><br></pre></td></tr></table></figure>
<p>说明：上述代码中，类对象 ex1、ex2 实际上是指向同一块内存空间，对象析构时，ex2 先将内存释放了一次，之后析构对象 ex1 时又将这块已经被释放过的内存再释放一次。对同一块内存空间释放了两次，会导致程序崩溃。</p>
<p><strong>深拷贝实例</strong></p>
<figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;iostream&gt;</span></span></span><br><span class="line"></span><br><span class="line"><span class="keyword">using</span> <span class="keyword">namespace</span> std;</span><br><span class="line"></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Test</span></span></span><br><span class="line"><span class="class">&#123;</span></span><br><span class="line"><span class="keyword">private</span>:</span><br><span class="line">	<span class="keyword">int</span> *p;</span><br><span class="line"></span><br><span class="line"><span class="keyword">public</span>:</span><br><span class="line">	<span class="built_in">Test</span>(<span class="keyword">int</span> tmp)</span><br><span class="line">	&#123;</span><br><span class="line">		p = <span class="keyword">new</span> <span class="built_in"><span class="keyword">int</span></span>(tmp);</span><br><span class="line">		cout &lt;&lt; <span class="string">&quot;Test(int tmp)&quot;</span> &lt;&lt; endl;</span><br><span class="line">	&#125;</span><br><span class="line">	~<span class="built_in">Test</span>()</span><br><span class="line">	&#123;</span><br><span class="line">		<span class="keyword">if</span> (p != <span class="literal">NULL</span>)</span><br><span class="line">		&#123;</span><br><span class="line">			<span class="keyword">delete</span> p;</span><br><span class="line">		&#125;</span><br><span class="line">		cout &lt;&lt; <span class="string">&quot;~Test()&quot;</span> &lt;&lt; endl;</span><br><span class="line">	&#125;</span><br><span class="line">	<span class="built_in">Test</span>(<span class="keyword">const</span> Test &amp;tmp) <span class="comment">// 定义拷贝构造函数</span></span><br><span class="line">	&#123;</span><br><span class="line">		p = <span class="keyword">new</span> <span class="built_in"><span class="keyword">int</span></span>(*tmp.p);</span><br><span class="line">		cout &lt;&lt; <span class="string">&quot;Test(const Test &amp;tmp)&quot;</span> &lt;&lt; endl;</span><br><span class="line">	&#125;</span><br><span class="line"></span><br><span class="line">&#125;;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">int</span> <span class="title">main</span><span class="params">()</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">	<span class="function">Test <span class="title">ex1</span><span class="params">(<span class="number">10</span>)</span></span>;	</span><br><span class="line">	Test ex2 = ex1; </span><br><span class="line">	<span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">&#125;</span><br><span class="line"><span class="comment">/*</span></span><br><span class="line"><span class="comment">Test(int tmp)</span></span><br><span class="line"><span class="comment">Test(const Test &amp;tmp)</span></span><br><span class="line"><span class="comment">~Test()</span></span><br><span class="line"><span class="comment">~Test()</span></span><br><span class="line"><span class="comment">*/</span></span><br></pre></td></tr></table></figure>
<h2 id="20-编译时多态和运行时多态的区别"><a class="markdownIt-Anchor" href="#20-编译时多态和运行时多态的区别"></a> 20、编译时多态和运行时多态的区别</h2>
<p>面试高频指数：三星</p>
<hr>
<p>编译时多态：在程序编译过程中出现，发生在模板和函数重载中（泛型编程）。</p>
<p>运行时多态：在程序运行过程中出现，发生在继承体系中，是指通过基类的指针或引用访问派生类中的虚函数。</p>
<p>编译时多态和运行时多态的区别：</p>
<ul>
<li>时期不同：编译时多态发生在程序编译过程中，运行时多态发生在程序的运行过程中；</li>
<li>实现方式不同：编译时多态运用泛型编程来实现，运行时多态借助虚函数来实现。</li>
</ul>
<h2 id="21-实现一个类成员函数要求不允许修改类的成员变量"><a class="markdownIt-Anchor" href="#21-实现一个类成员函数要求不允许修改类的成员变量"></a> 21、实现一个类成员函数，要求不允许修改类的成员变量？</h2>
<p>面试高频指数：两星</p>
<hr>
<p>如果想达到一个类的成员函数不能修改类的成员变量，只需用 <code>const</code> 关键字来修饰该函数即可。</p>
<p>该问题本质是考查 <code>const</code> 关键字修饰成员函数的作用，只不过以实例的方式来考查，面试者应熟练掌握 <code>const</code> 关键字的作用。</p>
<figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;iostream&gt;</span></span></span><br><span class="line"></span><br><span class="line"><span class="keyword">using</span> <span class="keyword">namespace</span> std;</span><br><span class="line"></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">A</span></span></span><br><span class="line"><span class="class">&#123;</span></span><br><span class="line"><span class="keyword">public</span>:</span><br><span class="line">    <span class="keyword">int</span> var1, var2;</span><br><span class="line">    <span class="built_in">A</span>()</span><br><span class="line">    &#123;</span><br><span class="line">        var1 = <span class="number">10</span>;</span><br><span class="line">        var2 = <span class="number">20</span>;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="function"><span class="keyword">void</span> <span class="title">fun</span><span class="params">()</span> <span class="keyword">const</span> <span class="comment">// 不能在 const 修饰的成员函数中修改成员变量的值，除非该成员变量用 mutable 修饰</span></span></span><br><span class="line"><span class="function">    </span>&#123;</span><br><span class="line">        var1 = <span class="number">100</span>; <span class="comment">// error: assignment of member &#x27;A::var1&#x27; in read-only object</span></span><br><span class="line">    &#125;</span><br><span class="line">&#125;;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">int</span> <span class="title">main</span><span class="params">()</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">    A ex1;</span><br><span class="line">    <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<h2 id="22-如何让类不能被继承"><a class="markdownIt-Anchor" href="#22-如何让类不能被继承"></a> 22、如何让类不能被继承？</h2>
<p>面试高频指数：三星</p>
<hr>
<p>解决方法一：借助 <code>final</code> 关键字，用该关键字修饰的类不能被继承。</p>
<figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;iostream&gt;</span></span></span><br><span class="line"></span><br><span class="line"><span class="keyword">using</span> <span class="keyword">namespace</span> std;</span><br><span class="line"></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Base</span> <span class="keyword">final</span></span></span><br><span class="line"><span class="class">&#123;</span></span><br><span class="line">&#125;;</span><br><span class="line"></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Derive</span>:</span> <span class="keyword">public</span> Base&#123; <span class="comment">// error: cannot derive from &#x27;final&#x27; base &#x27;Base&#x27; in derived type &#x27;Derive&#x27;</span></span><br><span class="line"></span><br><span class="line">&#125;;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">int</span> <span class="title">main</span><span class="params">()</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">    Derive ex;</span><br><span class="line">    <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>解决方法二：借助友元、虚继承和四有构造函数来实现</p>
<figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;iostream&gt;</span></span></span><br><span class="line"><span class="keyword">using</span> <span class="keyword">namespace</span> std;</span><br><span class="line"></span><br><span class="line"><span class="keyword">template</span> &lt;<span class="keyword">typename</span> T&gt;</span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Base</span>&#123;</span></span><br><span class="line">    <span class="keyword">friend</span> T;</span><br><span class="line"><span class="keyword">private</span>:</span><br><span class="line">    <span class="built_in">Base</span>()&#123;</span><br><span class="line">        cout &lt;&lt; <span class="string">&quot;base&quot;</span> &lt;&lt; endl;</span><br><span class="line">    &#125;</span><br><span class="line">    ~<span class="built_in">Base</span>()&#123;&#125;</span><br><span class="line">&#125;;</span><br><span class="line"></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">B</span>:</span><span class="keyword">virtual</span> <span class="keyword">public</span> Base&lt;B&gt;&#123;   <span class="comment">//一定注意 必须是虚继承</span></span><br><span class="line"><span class="keyword">public</span>:</span><br><span class="line">    <span class="built_in">B</span>()&#123;</span><br><span class="line">        cout &lt;&lt; <span class="string">&quot;B&quot;</span> &lt;&lt; endl;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;;</span><br><span class="line"></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">C</span>:</span><span class="keyword">public</span> B&#123;</span><br><span class="line"><span class="keyword">public</span>:</span><br><span class="line">    <span class="built_in">C</span>()&#123;&#125;     <span class="comment">// error: &#x27;Base&lt;T&gt;::Base() [with T = B]&#x27; is private within this context</span></span><br><span class="line">&#125;;</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">int</span> <span class="title">main</span><span class="params">()</span></span>&#123;</span><br><span class="line">    B b;  </span><br><span class="line">    <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>说明：在上述代码中 <code>B</code> 类是不能被继承的类。</p>
<p>具体原因：</p>
<ul>
<li>虽然 <code>Base</code> 类构造函数和析构函数被声明为私有 <code>private</code>，在 <code>B</code> 类中，由于 <code>B</code> 是 <code>Base</code> 的友元，因此可以访问 <code>Base</code> 类构造函数，从而正常创建 <code>B</code> 类的对象；</li>
<li><code>B</code> 类继承 <code>Base</code> 类采用虚继承的方式，创建 <code>C</code> 类的对象时，<code>C</code> 类的构造函数要负责 <code>Base</code> 类的构造，但是 <code>Base</code> 类的构造函数私有化了，<code>C</code> 类没有权限访问。因此，无法创建<code>C</code> 类的对象，<code>B</code> 类是不能被继承的类。</li>
</ul>
<p>注意：在继承体系中，友元关系不能被继承，虽然 <code>C</code> 类继承了 <code>B</code> 类，<code>B</code> 类是 <code>Base</code> 类的友元，但是<code>C</code> 类和 <code>Base</code> 类没有友元关系。</p>
<h1 id="六-语言特性相关"><a class="markdownIt-Anchor" href="#六-语言特性相关"></a> 六、语言特性相关</h1>
<h2 id="1-左值和右值的区别左值引用和右值引用的区别如何将左值转换成右值"><a class="markdownIt-Anchor" href="#1-左值和右值的区别左值引用和右值引用的区别如何将左值转换成右值"></a> 1、左值和右值的区别？左值引用和右值引用的区别，如何将左值转换成右值？</h2>
<p>面试高频指数：四星</p>
<hr>
<p>左值：指表达式结束后依然存在的持久对象。</p>
<p>右值：表达式结束后不再存在的临时对象。</p>
<p>左值和右值的区别：左值持久，右值短暂。</p>
<p>左值引用和右值引用的区别：</p>
<ul>
<li>左值引用不能绑定到要转换的表达式、字面常量或返回右值的表达式。右值引用恰好相反，可以绑定到这类表达式，但不能绑定到一个左值上。</li>
<li>右值引用必须绑定到右值的引用，通过 <code>&amp;&amp;</code> 获得。右值引用只能绑定到一个将要销毁的对象上，因此可以自由地移动其资源。</li>
</ul>
<p><code>std::move</code>可以将一个左值强制转化为右值，继而可以通过右值引用使用该值，以用于移动语义。</p>
<figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;iostream&gt;</span></span></span><br><span class="line"><span class="keyword">using</span> <span class="keyword">namespace</span> std;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">void</span> <span class="title">fun1</span><span class="params">(<span class="keyword">int</span>&amp; tmp)</span> </span></span><br><span class="line"><span class="function"></span>&#123; </span><br><span class="line">  cout &lt;&lt; <span class="string">&quot;fun1(int&amp; tmp):&quot;</span> &lt;&lt; tmp &lt;&lt; endl; </span><br><span class="line">&#125; </span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">void</span> <span class="title">fun2</span><span class="params">(<span class="keyword">int</span>&amp;&amp; tmp)</span> </span></span><br><span class="line"><span class="function"></span>&#123; </span><br><span class="line">  cout &lt;&lt; <span class="string">&quot;fun2(int&amp;&amp; tmp)&quot;</span> &lt;&lt; tmp &lt;&lt; endl; </span><br><span class="line">&#125; </span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">int</span> <span class="title">main</span><span class="params">()</span> </span></span><br><span class="line"><span class="function"></span>&#123; </span><br><span class="line">  <span class="keyword">int</span> var = <span class="number">11</span>; </span><br><span class="line">  <span class="built_in">fun1</span>(<span class="number">12</span>); <span class="comment">// error: cannot bind non-const lvalue reference of type &#x27;int&amp;&#x27; to an rvalue of type &#x27;int&#x27;</span></span><br><span class="line">  <span class="built_in">fun1</span>(var);</span><br><span class="line">  <span class="built_in">fun2</span>(<span class="number">1</span>); </span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<h2 id="2-stdmove-函数的实现原理"><a class="markdownIt-Anchor" href="#2-stdmove-函数的实现原理"></a> 2、std::move() 函数的实现原理</h2>
<p>面试高频指数：三星</p>
<hr>
<p><code>std::move()</code>函数原型：</p>
<figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">template</span> &lt;<span class="keyword">typename</span> T&gt;</span><br><span class="line"><span class="keyword">typename</span> remove_reference&lt;T&gt;::<span class="function">type&amp;&amp; <span class="title">move</span><span class="params">(T&amp;&amp; t)</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">	<span class="keyword">return</span> <span class="keyword">static_cast</span>&lt;<span class="keyword">typename</span> remove_reference&lt;T&gt;::type &amp;&amp;&gt;(t);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>说明：引用折叠原理</p>
<ul>
<li>右值传递给上述函数的形参 <code>T&amp;&amp;</code> 依然是右值，即 <code>T&amp;&amp; &amp;&amp;</code> 相当于 <code>T&amp;&amp;</code>。</li>
<li>左值传递给上述函数的形参 <code>T&amp;&amp;</code> 依然是左值，即 <code>T&amp;&amp; &amp;</code> 相当于 <code>T&amp;</code>。</li>
</ul>
<p>小结：通过引用折叠原理可以知道，<code>move()</code> 函数的形参既可以是左值也可以是右值。</p>
<p><code>remove_reference</code>具体实现：</p>
<figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">//原始的，最通用的版本</span></span><br><span class="line"><span class="keyword">template</span> &lt;<span class="keyword">typename</span> T&gt; <span class="class"><span class="keyword">struct</span> <span class="title">remove_reference</span>&#123;</span></span><br><span class="line">    <span class="keyword">typedef</span> T type;  <span class="comment">//定义 T 的类型别名为 type</span></span><br><span class="line">&#125;;</span><br><span class="line"> </span><br><span class="line"><span class="comment">//部分版本特例化，将用于左值引用和右值引用</span></span><br><span class="line"><span class="keyword">template</span> &lt;<span class="class"><span class="keyword">class</span> <span class="title">T</span>&gt;</span> <span class="class"><span class="keyword">struct</span> <span class="title">remove_reference</span>&lt;</span>T&amp;&gt; <span class="comment">//左值引用</span></span><br><span class="line">&#123; <span class="keyword">typedef</span> T type; &#125;</span><br><span class="line"> </span><br><span class="line"><span class="keyword">template</span> &lt;<span class="class"><span class="keyword">class</span> <span class="title">T</span>&gt;</span> <span class="class"><span class="keyword">struct</span> <span class="title">remove_reference</span>&lt;</span>T&amp;&amp;&gt; <span class="comment">//右值引用</span></span><br><span class="line">&#123; <span class="keyword">typedef</span> T type; &#125;   </span><br><span class="line">  </span><br><span class="line"><span class="comment">//举例如下,下列定义的a、b、c三个变量都是int类型</span></span><br><span class="line"><span class="keyword">int</span> i;</span><br><span class="line">remove_refrence&lt;<span class="keyword">decltype</span>(<span class="number">42</span>)&gt;::type a;             <span class="comment">//使用原版本，</span></span><br><span class="line">remove_refrence&lt;<span class="keyword">decltype</span>(i)&gt;::type  b;             <span class="comment">//左值引用特例版本</span></span><br><span class="line">remove_refrence&lt;<span class="keyword">decltype</span>(std::<span class="built_in">move</span>(i))&gt;::type  b;  <span class="comment">//右值引用特例版本 </span></span><br></pre></td></tr></table></figure>
<p>举例：</p>
<figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">int</span> var = <span class="number">10</span>; </span><br><span class="line"></span><br><span class="line">转化过程：</span><br><span class="line"><span class="number">1.</span> std::<span class="built_in">move</span>(var) =&gt; std::<span class="built_in">move</span>(<span class="keyword">int</span>&amp;&amp; &amp;) =&gt; 折叠后 std::<span class="built_in">move</span>(<span class="keyword">int</span>&amp;)</span><br><span class="line"></span><br><span class="line"><span class="number">2.</span> 此时：T 的类型为 <span class="keyword">int</span>&amp;，<span class="keyword">typename</span> remove_reference&lt;T&gt;::type 为 <span class="keyword">int</span>，这里使用 remove_reference 的左值引用的特例化版本</span><br><span class="line"></span><br><span class="line"><span class="number">3.</span> 通过 <span class="keyword">static_cast</span> 将 <span class="keyword">int</span>&amp; 强制转换为 <span class="keyword">int</span>&amp;&amp;</span><br><span class="line"></span><br><span class="line">整个std::move被实例化如下</span><br><span class="line">string&amp;&amp; <span class="built_in">move</span>(<span class="keyword">int</span>&amp; t) </span><br><span class="line">&#123;</span><br><span class="line">    <span class="keyword">return</span> <span class="keyword">static_cast</span>&lt;<span class="keyword">int</span>&amp;&amp;&gt;(t); </span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>总结：</p>
<p><code>std::move()</code>实现原理：</p>
<ol>
<li>利用引用折叠原理将右值经过 <code>T&amp;&amp;</code> 传递类型保持不变还是右值，而左值经过 <code>T&amp;&amp;</code> 变为普通的左值引用，以保证模板可以传递任意实参，且保持类型不变；</li>
<li>然后通过 <code>remove_reference</code> 移除引用，得到具体的类型 <code>T</code>；</li>
<li>最后通过 <code>static_case&lt;&gt;</code> 进行强制类型转换，返回 <code>T&amp;&amp;</code> 右值引用。</li>
</ol>
<h2 id="3-什么是指针指针的大小及用法"><a class="markdownIt-Anchor" href="#3-什么是指针指针的大小及用法"></a> 3、什么是指针？指针的大小及用法？</h2>
<p>面试高频指数：两星</p>
<hr>
<p>**指针：**指向另外一种类型的复合类型。</p>
<p>**指针的大小：**在 64 位计算机中，指针占 8 个字节空间。</p>
<figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="meta-keyword">include</span><span class="meta-string">&lt;iostream&gt;</span></span></span><br><span class="line"></span><br><span class="line"><span class="keyword">using</span> <span class="keyword">namespace</span> std;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">int</span> <span class="title">main</span><span class="params">()</span></span>&#123;</span><br><span class="line">    <span class="keyword">int</span> *p = <span class="literal">nullptr</span>;</span><br><span class="line">    cout &lt;&lt; <span class="built_in"><span class="keyword">sizeof</span></span>(p) &lt;&lt; endl; <span class="comment">// 8</span></span><br><span class="line"></span><br><span class="line">    <span class="keyword">char</span> *p1 = <span class="literal">nullptr</span>;</span><br><span class="line">    cout &lt;&lt; <span class="built_in"><span class="keyword">sizeof</span></span>(p1) &lt;&lt; endl; <span class="comment">// 8</span></span><br><span class="line">    <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p><strong>指针的用法：</strong></p>
<ol>
<li>
<p>指向普通对象的指针</p>
 <figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;iostream&gt;</span></span></span><br><span class="line"></span><br><span class="line"><span class="keyword">using</span> <span class="keyword">namespace</span> std;</span><br><span class="line"></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">A</span></span></span><br><span class="line"><span class="class">&#123;</span></span><br><span class="line">&#125;;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">int</span> <span class="title">main</span><span class="params">()</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">    A *p = <span class="keyword">new</span> <span class="built_in">A</span>();</span><br><span class="line">    <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
</li>
<li>
<p>指向常量对象的指针：常量指针</p>
 <figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;iostream&gt;</span></span></span><br><span class="line"><span class="keyword">using</span> <span class="keyword">namespace</span> std;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">int</span> <span class="title">main</span><span class="params">(<span class="keyword">void</span>)</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">    <span class="keyword">const</span> <span class="keyword">int</span> c_var = <span class="number">10</span>;</span><br><span class="line">    <span class="keyword">const</span> <span class="keyword">int</span> * p = &amp;c_var;</span><br><span class="line">    cout &lt;&lt; *p &lt;&lt; endl;</span><br><span class="line">    <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
</li>
<li>
<p>指向函数的指针：函数指针</p>
 <figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;iostream&gt;</span></span></span><br><span class="line"><span class="keyword">using</span> <span class="keyword">namespace</span> std;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">int</span> <span class="title">add</span><span class="params">(<span class="keyword">int</span> a, <span class="keyword">int</span> b)</span></span>&#123;</span><br><span class="line">    <span class="keyword">return</span> a + b;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">int</span> <span class="title">main</span><span class="params">(<span class="keyword">void</span>)</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">    <span class="built_in"><span class="keyword">int</span></span> (*fun_p)(<span class="keyword">int</span>, <span class="keyword">int</span>);</span><br><span class="line">    fun_p = add;</span><br><span class="line">    cout &lt;&lt; <span class="built_in">fun_p</span>(<span class="number">1</span>, <span class="number">6</span>) &lt;&lt; endl;</span><br><span class="line">    <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
</li>
<li>
<p>指向对象成员的指针，包括指向对象成员函数的指针和指向对象成员变量的指针</p>
<p>特别注意：定义指向成员函数的指针时，要标明指针所属的类。</p>
 <figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;iostream&gt;</span></span></span><br><span class="line"></span><br><span class="line"><span class="keyword">using</span> <span class="keyword">namespace</span> std;</span><br><span class="line"></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">A</span></span></span><br><span class="line"><span class="class">&#123;</span></span><br><span class="line"><span class="keyword">public</span>:</span><br><span class="line">    <span class="keyword">int</span> var1, var2; </span><br><span class="line">    <span class="function"><span class="keyword">int</span> <span class="title">add</span><span class="params">()</span></span>&#123;</span><br><span class="line">        <span class="keyword">return</span> var1 + var2;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">int</span> <span class="title">main</span><span class="params">()</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">    A ex;</span><br><span class="line">    ex.var1 = <span class="number">3</span>;</span><br><span class="line">    ex.var2 = <span class="number">4</span>;</span><br><span class="line">    <span class="keyword">int</span> *p = &amp;ex.var1; <span class="comment">// 指向对象成员变量的指针</span></span><br><span class="line">    cout &lt;&lt; *p &lt;&lt; endl;</span><br><span class="line"></span><br><span class="line">    <span class="built_in"><span class="keyword">int</span></span> (A::*fun_p)();</span><br><span class="line">    fun_p = &amp;A::add; <span class="comment">// 指向对象成员函数的指针 fun_p</span></span><br><span class="line">    cout &lt;&lt; (ex.*fun_p)() &lt;&lt; endl;</span><br><span class="line">    <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
</li>
<li>
<p>this 指针：指向类的当前对象的指针常量。</p>
 <figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;iostream&gt;</span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;cstring&gt;</span></span></span><br><span class="line"><span class="keyword">using</span> <span class="keyword">namespace</span> std;</span><br><span class="line"></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">A</span></span></span><br><span class="line"><span class="class">&#123;</span></span><br><span class="line"><span class="keyword">public</span>:</span><br><span class="line">    <span class="function"><span class="keyword">void</span> <span class="title">set_name</span><span class="params">(string tmp)</span></span></span><br><span class="line"><span class="function">    </span>&#123;</span><br><span class="line">        <span class="keyword">this</span>-&gt;name = tmp;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="function"><span class="keyword">void</span> <span class="title">set_age</span><span class="params">(<span class="keyword">int</span> tmp)</span></span></span><br><span class="line"><span class="function">    </span>&#123;</span><br><span class="line">        <span class="keyword">this</span>-&gt;age = age;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="function"><span class="keyword">void</span> <span class="title">set_sex</span><span class="params">(<span class="keyword">int</span> tmp)</span></span></span><br><span class="line"><span class="function">    </span>&#123;</span><br><span class="line">        <span class="keyword">this</span>-&gt;sex = tmp;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="function"><span class="keyword">void</span> <span class="title">show</span><span class="params">()</span></span></span><br><span class="line"><span class="function">    </span>&#123;</span><br><span class="line">        cout &lt;&lt; <span class="string">&quot;Name: &quot;</span> &lt;&lt; <span class="keyword">this</span>-&gt;name &lt;&lt; endl;</span><br><span class="line">        cout &lt;&lt; <span class="string">&quot;Age: &quot;</span> &lt;&lt; <span class="keyword">this</span>-&gt;age &lt;&lt; endl;</span><br><span class="line">        cout &lt;&lt; <span class="string">&quot;Sex: &quot;</span> &lt;&lt; <span class="keyword">this</span>-&gt;sex &lt;&lt; endl;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">private</span>:</span><br><span class="line">    string name;</span><br><span class="line">    <span class="keyword">int</span> age;</span><br><span class="line">    <span class="keyword">int</span> sex;</span><br><span class="line">&#125;;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">int</span> <span class="title">main</span><span class="params">()</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">    A *p = <span class="keyword">new</span> <span class="built_in">A</span>();</span><br><span class="line">    p-&gt;<span class="built_in">set_name</span>(<span class="string">&quot;Alice&quot;</span>);</span><br><span class="line">    p-&gt;<span class="built_in">set_age</span>(<span class="number">16</span>);</span><br><span class="line">    p-&gt;<span class="built_in">set_sex</span>(<span class="number">1</span>);</span><br><span class="line">    p-&gt;<span class="built_in">show</span>();</span><br><span class="line"></span><br><span class="line">    <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
</li>
</ol>
<h2 id="4-什么是野指针和悬空指针"><a class="markdownIt-Anchor" href="#4-什么是野指针和悬空指针"></a> 4、什么是野指针和悬空指针？</h2>
<p>面试高频指数：三星</p>
<hr>
<p>悬空指针：若指针指向一块内存空间，当这块内存空间被释放后，该指针依然指向这块内存空间，此时，称该指针为”悬空指针“。</p>
<p>举例：</p>
<figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">void</span> *p = <span class="built_in">malloc</span>(size);</span><br><span class="line"><span class="built_in">free</span>(p); </span><br><span class="line"><span class="comment">// 此时，p 指向的内存空间已释放， p 就是悬空指针。</span></span><br></pre></td></tr></table></figure>
<p>野指针：”野指针“是指不确定其指向的指针，未初始化的指针为”野指针“。</p>
<figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">void</span> *p; </span><br><span class="line"><span class="comment">// 此时 p 是“野指针”。</span></span><br></pre></td></tr></table></figure>
<h2 id="5-c-11-nullptr-比-null-优势"><a class="markdownIt-Anchor" href="#5-c-11-nullptr-比-null-优势"></a> 5、C++ 11 nullptr 比 NULL 优势</h2>
<p>面试高频指数：1星</p>
<hr>
<ul>
<li><code>NULL</code>：预处理变量，是一个宏，它的值是 0，定义在头文件 <code>&lt;cstdlib&gt;</code> 中，即 <code>#define NULL 0</code>。</li>
<li><code>nullptr</code>：C++ 11  中的关键字，是一种特殊类型的字面值，可以被转换成任意其它类型。</li>
</ul>
<p><code>nullptr</code> 的优势：</p>
<ol>
<li>有类型，类型是 <code>typedef decltype(nullptr) nullptr_t;</code>，使用 <code>nullptr</code> 提高代码的健壮性。</li>
<li>函数重载：因为 <code>NULL</code> 本质上是 0，在函数调用过程中，若出现函数重载并且传递的实参是 <code>NULL</code>，可能会出现，不知和哪一个函数匹配的情况；但是传递实参 <code>nullptr</code> 就不会出现这种情况。</li>
</ol>
<figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;iostream&gt;</span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;cstring&gt;</span></span></span><br><span class="line"><span class="keyword">using</span> <span class="keyword">namespace</span> std;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">void</span> <span class="title">fun</span><span class="params">(<span class="keyword">char</span> <span class="keyword">const</span> *p)</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">    cout &lt;&lt; <span class="string">&quot;fun(char const *p)&quot;</span> &lt;&lt; endl;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">void</span> <span class="title">fun</span><span class="params">(<span class="keyword">int</span> tmp)</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">    cout &lt;&lt; <span class="string">&quot;fun(int tmp)&quot;</span> &lt;&lt; endl;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">int</span> <span class="title">main</span><span class="params">()</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">    <span class="built_in">fun</span>(<span class="literal">nullptr</span>); <span class="comment">// fun(char const *p)</span></span><br><span class="line">    <span class="comment">/*</span></span><br><span class="line"><span class="comment">    fun(NULL); // error: call of overloaded &#x27;fun(NULL)&#x27; is ambiguous</span></span><br><span class="line"><span class="comment">    */</span></span><br><span class="line">    <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<h2 id="6-指针和引用的区别"><a class="markdownIt-Anchor" href="#6-指针和引用的区别"></a> 6、指针和引用的区别？</h2>
<p>面试高频指数：四星</p>
<hr>
<ul>
<li>指针所指向的内存空间在程序运行过程中可以改变，而引用所绑定的对象一旦绑定就不能改变。（是否可变）</li>
<li>指针本身在内存中占有内存空间，引用相当于变量的别名，在内存中不占内存空间。（是否占内存）</li>
<li>指针可以为空，但是引用必须绑定对象。（是否可为空）</li>
<li>指针可以有多级，但是引用只能一级。（是否能为多级）</li>
</ul>
<h2 id="7-常量指针和指针常量的区别"><a class="markdownIt-Anchor" href="#7-常量指针和指针常量的区别"></a> 7、常量指针和指针常量的区别</h2>
<p>面试高频指数：四星</p>
<hr>
<p><strong>常量指针</strong>：</p>
<p>常量指针本质上是个指针，只不过这个指针指向的对象是常量。</p>
<p>特点：<code>const</code> 的位置在指针声明运算符 <code>*</code> 的左侧。只要 <code>const</code> 位于 <code>*</code> 的左侧，无论他在类型名的左边或右边，都表示指向常量的指针。（可以这样理解，<code>*</code> 左侧表示指针指向的对象，该对象为常量，那么该指针为常量指针。）</p>
<figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">const</span> <span class="keyword">int</span> * p;</span><br><span class="line"><span class="keyword">int</span> <span class="keyword">const</span> * p;</span><br></pre></td></tr></table></figure>
<p>注意1：指针指向的对象不能通过这个指针来修改，也就是说常量指针可以被赋值为变量的地址，之所以叫做常量指针，是限制了通过这个指针修改变量的值。</p>
<p>例如：</p>
<figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;iostream&gt;</span></span></span><br><span class="line"><span class="keyword">using</span> <span class="keyword">namespace</span> std;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">int</span> <span class="title">main</span><span class="params">()</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">    <span class="keyword">const</span> <span class="keyword">int</span> c_var = <span class="number">8</span>;</span><br><span class="line">    <span class="keyword">const</span> <span class="keyword">int</span> *p = &amp;c_var; </span><br><span class="line">    *p = <span class="number">6</span>;            <span class="comment">// error: assignment of read-only location &#x27;* p&#x27;</span></span><br><span class="line">    <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>注意2：虽然常量指针指向的对象不能变化，可是因为常量指针本身是一个变量，因此，可以被重新赋值。</p>
<p>例如：</p>
<figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;iostream&gt;</span></span></span><br><span class="line"><span class="keyword">using</span> <span class="keyword">namespace</span> std;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">int</span> <span class="title">main</span><span class="params">()</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">    <span class="keyword">const</span> <span class="keyword">int</span> c_var1 = <span class="number">8</span>;</span><br><span class="line">    <span class="keyword">const</span> <span class="keyword">int</span> c_var2 = <span class="number">8</span>;</span><br><span class="line">    <span class="keyword">const</span> <span class="keyword">int</span> *p = &amp;c_var1; </span><br><span class="line">    p = &amp;c_var2;</span><br><span class="line">    <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p><strong>指针常量：</strong></p>
<p>指针常量的本质上是个常量，只不过这个常量的值是一个指针。</p>
<p>特点：<code>const</code> 位于指针声明操作符右侧，表明该对象本身是一个常量，<code>*</code> 左侧表示该指针指向的类型，即以 <code>*</code> 为分界线，其左侧表示指针指向的类型，右侧表示指针本身的性质。</p>
<figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">const</span> <span class="keyword">int</span> var;</span><br><span class="line"><span class="keyword">int</span> * <span class="keyword">const</span> c_p = &amp;var; </span><br></pre></td></tr></table></figure>
<p>注意1：指针常量的值是指针，这个值因为是常量，所以指针本身不能改变。</p>
<figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;iostream&gt;</span></span></span><br><span class="line"><span class="keyword">using</span> <span class="keyword">namespace</span> std;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">int</span> <span class="title">main</span><span class="params">()</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">    <span class="keyword">int</span> var, var1;</span><br><span class="line">    <span class="keyword">int</span> * <span class="keyword">const</span> c_p = &amp;var;</span><br><span class="line">    c_p = &amp;var1; <span class="comment">// error: assignment of read-only variable &#x27;c_p&#x27;</span></span><br><span class="line">    <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>注意2：指针的内容可以改变。</p>
<figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;iostream&gt;</span></span></span><br><span class="line"><span class="keyword">using</span> <span class="keyword">namespace</span> std;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">int</span> <span class="title">main</span><span class="params">()</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">    <span class="keyword">int</span> var = <span class="number">3</span>;</span><br><span class="line">    <span class="keyword">int</span> * <span class="keyword">const</span> c_p = &amp;var;</span><br><span class="line">    *c_p = <span class="number">12</span>; </span><br><span class="line">    <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<h2 id="8-函数指针和指针函数的区别"><a class="markdownIt-Anchor" href="#8-函数指针和指针函数的区别"></a> 8、函数指针和指针函数的区别</h2>
<p>面试高频指数：四星</p>
<hr>
<p><strong>指针函数：</strong></p>
<p>指针函数本质是一个函数，只不过该函数的返回值是一个指针。相对于普通函数而言，只是返回值是指针。</p>
<figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;iostream&gt;</span></span></span><br><span class="line"><span class="keyword">using</span> <span class="keyword">namespace</span> std;</span><br><span class="line"></span><br><span class="line"><span class="class"><span class="keyword">struct</span> <span class="title">Type</span></span></span><br><span class="line"><span class="class">&#123;</span></span><br><span class="line">  <span class="keyword">int</span> var1;</span><br><span class="line">  <span class="keyword">int</span> var2;</span><br><span class="line">&#125;;</span><br><span class="line"></span><br><span class="line"><span class="function">Type * <span class="title">fun</span><span class="params">(<span class="keyword">int</span> tmp1, <span class="keyword">int</span> tmp2)</span></span>&#123;</span><br><span class="line">    Type * t = <span class="keyword">new</span> <span class="built_in">Type</span>();</span><br><span class="line">    t-&gt;var1 = tmp1;</span><br><span class="line">    t-&gt;var2 = tmp2;</span><br><span class="line">    <span class="keyword">return</span> t;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">int</span> <span class="title">main</span><span class="params">()</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">    Type *p = <span class="built_in">fun</span>(<span class="number">5</span>, <span class="number">6</span>);</span><br><span class="line">    <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p><strong>函数指针：</strong></p>
<p>函数指针本质是一个指针变量，只不过这个指针指向一个函数。函数指针即指向函数的指针。</p>
<p>举例：</p>
<figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;iostream&gt;</span></span></span><br><span class="line"><span class="keyword">using</span> <span class="keyword">namespace</span> std;</span><br><span class="line"><span class="function"><span class="keyword">int</span> <span class="title">fun1</span><span class="params">(<span class="keyword">int</span> tmp1, <span class="keyword">int</span> tmp2)</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">  <span class="keyword">return</span> tmp1 * tmp2;</span><br><span class="line">&#125;</span><br><span class="line"><span class="function"><span class="keyword">int</span> <span class="title">fun2</span><span class="params">(<span class="keyword">int</span> tmp1, <span class="keyword">int</span> tmp2)</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">  <span class="keyword">return</span> tmp1 / tmp2;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">int</span> <span class="title">main</span><span class="params">()</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">  <span class="built_in"><span class="keyword">int</span></span> (*fun)(<span class="keyword">int</span> x, <span class="keyword">int</span> y); </span><br><span class="line">  fun = fun1;</span><br><span class="line">  cout &lt;&lt; <span class="built_in">fun</span>(<span class="number">15</span>, <span class="number">5</span>) &lt;&lt; endl; </span><br><span class="line">  fun = fun2;</span><br><span class="line">  cout &lt;&lt; <span class="built_in">fun</span>(<span class="number">15</span>, <span class="number">5</span>) &lt;&lt; endl; </span><br><span class="line">  <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">&#125;</span><br><span class="line"><span class="comment">/*</span></span><br><span class="line"><span class="comment">运行结果：</span></span><br><span class="line"><span class="comment">75</span></span><br><span class="line"><span class="comment">3</span></span><br><span class="line"><span class="comment">*/</span></span><br></pre></td></tr></table></figure>
<p><strong>函数指针和指针函数的区别：</strong></p>
<ul>
<li>本质不同
<ul>
<li>指针函数本质是一个函数，其返回值为指针。</li>
<li>函数指针本质上是一个指针变量，其指向一个函数。</li>
</ul>
</li>
<li>定义形式不同
<ul>
<li>指针函数：<code>int* fun(int tmp1, int tmp2);</code>，这里 <code>*</code> 表示函数的返回值类型是指针类型。</li>
<li>函数指针：<code>int (*fun)(int tmp1, int tmp2);</code>，这里 <code>*</code> 表示变量本身是指针类型。</li>
</ul>
</li>
<li>用法不同</li>
</ul>
<h2 id="9-强制类型转换有哪几种"><a class="markdownIt-Anchor" href="#9-强制类型转换有哪几种"></a> 9、强制类型转换有哪几种？</h2>
<p>面试高频指数：四星</p>
<hr>
<ul>
<li>
<p><code>static_cast</code>：用于数据的强制类型转换，强制将一种数据类型转换为另一种数据类型。</p>
<ol>
<li>用于基本数据类型的转换。</li>
<li>用于类层次之间的基类和派生类之间 <strong>指针或者引用</strong> 的转换（<strong>不要求必须包含虚函数，但必须是有相互联系的类</strong>），进行上行转换（派生类的指针或引用转换成基类表示）是安全的；进行下行转换（基类的指针或引用转换成派生类表示）由于没有动态类型检查，所以是不安全的，最好用 <code>dynamic_cast</code>进行下行转换。</li>
<li>可以将空指针转化成目标类型的空指针。</li>
<li>可以将任何类型的表达式转换成 <code>void</code> 类型。</li>
</ol>
</li>
<li>
<p><code>const_cast</code>：强制去掉常量属性，不能用于去掉变量的常量性，只能用于去除指针或引用的常量性，将常量指针转化为非常量指针或者将常量引用转化为非常量引用（注意：表达式的类型和要转化的类型是相同的）。</p>
</li>
<li>
<p><code>reinterpret_cast</code>：改变指针或引用的类型、将指针或引用转换为一个足够长度的整型、将整型转化为指针或引用类型。</p>
</li>
<li>
<p><code>dynamic_cast</code>：</p>
<ol>
<li>
<p>其他三种都是编译时完成的，动态类型转换是在程序运行时处理的，运行时会进行类型检查。</p>
</li>
<li>
<p>只能用于带有虚函数的基类或派生类的指针或者引用对象的转换，转换成功返回指向类型的指针或引用，转换失败返回 <code>NULL</code>；不能用于基本数据类型的转换。</p>
</li>
<li>
<p>在向上进行转换时，即派生类类的指针转换成基类类的指针和 <code>static_cast</code> 效果是一样的，（注意：这里只是改变了指针的类型，指针指向的对象的类型并未发生改变）。</p>
 <figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;iostream&gt;</span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;cstring&gt;</span></span></span><br><span class="line"></span><br><span class="line"><span class="keyword">using</span> <span class="keyword">namespace</span> std;</span><br><span class="line"></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Base</span></span></span><br><span class="line"><span class="class">&#123;</span></span><br><span class="line">&#125;;</span><br><span class="line"></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Derive</span> :</span> <span class="keyword">public</span> Base</span><br><span class="line">&#123;</span><br><span class="line">&#125;;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">int</span> <span class="title">main</span><span class="params">()</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">    Base *p1 = <span class="keyword">new</span> <span class="built_in">Derive</span>();</span><br><span class="line">    Derive *p2 = <span class="keyword">new</span> <span class="built_in">Derive</span>();</span><br><span class="line"></span><br><span class="line">    <span class="comment">//向上类型转换</span></span><br><span class="line">    p1 = <span class="keyword">dynamic_cast</span>&lt;Base *&gt;(p2);</span><br><span class="line">    <span class="keyword">if</span> (p1 == <span class="literal">NULL</span>)</span><br><span class="line">    &#123;</span><br><span class="line">        cout &lt;&lt; <span class="string">&quot;NULL&quot;</span> &lt;&lt; endl;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">else</span></span><br><span class="line">    &#123;</span><br><span class="line">        cout &lt;&lt; <span class="string">&quot;NOT NULL&quot;</span> &lt;&lt; endl; <span class="comment">//输出</span></span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
</li>
<li>
<p>在下行转换时，基类的指针类型转化为派生类类的指针类型，只有当要转换的指针指向的对象类型和转化以后的对象类型相同时，才会转化成功。</p>
 <figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;iostream&gt;</span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;cstring&gt;</span></span></span><br><span class="line"></span><br><span class="line"><span class="keyword">using</span> <span class="keyword">namespace</span> std;</span><br><span class="line"></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Base</span></span></span><br><span class="line"><span class="class">&#123;</span></span><br><span class="line"><span class="keyword">public</span>:</span><br><span class="line">    <span class="function"><span class="keyword">virtual</span> <span class="keyword">void</span> <span class="title">fun</span><span class="params">()</span></span></span><br><span class="line"><span class="function">    </span>&#123;</span><br><span class="line">        cout &lt;&lt; <span class="string">&quot;Base::fun()&quot;</span> &lt;&lt; endl;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;;</span><br><span class="line"></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Derive</span> :</span> <span class="keyword">public</span> Base</span><br><span class="line">&#123;</span><br><span class="line"><span class="keyword">public</span>:</span><br><span class="line">    <span class="function"><span class="keyword">virtual</span> <span class="keyword">void</span> <span class="title">fun</span><span class="params">()</span></span></span><br><span class="line"><span class="function">    </span>&#123;</span><br><span class="line">        cout &lt;&lt; <span class="string">&quot;Derive::fun()&quot;</span> &lt;&lt; endl;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">int</span> <span class="title">main</span><span class="params">()</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">    Base *p1 = <span class="keyword">new</span> <span class="built_in">Derive</span>();</span><br><span class="line">    Base *p2 = <span class="keyword">new</span> <span class="built_in">Base</span>();</span><br><span class="line">    Derive *p3 = <span class="keyword">new</span> <span class="built_in">Derive</span>();</span><br><span class="line"></span><br><span class="line">    <span class="comment">//转换成功</span></span><br><span class="line">    p3 = <span class="keyword">dynamic_cast</span>&lt;Derive *&gt;(p1);</span><br><span class="line">    <span class="keyword">if</span> (p3 == <span class="literal">NULL</span>)</span><br><span class="line">    &#123;</span><br><span class="line">        cout &lt;&lt; <span class="string">&quot;NULL&quot;</span> &lt;&lt; endl;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">else</span></span><br><span class="line">    &#123;</span><br><span class="line">        cout &lt;&lt; <span class="string">&quot;NOT NULL&quot;</span> &lt;&lt; endl; <span class="comment">// 输出</span></span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="comment">//转换失败</span></span><br><span class="line">    p3 = <span class="keyword">dynamic_cast</span>&lt;Derive *&gt;(p2);</span><br><span class="line">    <span class="keyword">if</span> (p3 == <span class="literal">NULL</span>)</span><br><span class="line">    &#123;</span><br><span class="line">        cout &lt;&lt; <span class="string">&quot;NULL&quot;</span> &lt;&lt; endl; <span class="comment">// 输出</span></span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">else</span></span><br><span class="line">    &#123;</span><br><span class="line">        cout &lt;&lt; <span class="string">&quot;NOT NULL&quot;</span> &lt;&lt; endl;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
</li>
</ol>
</li>
</ul>
<h2 id="10-如何判断结构体是否相等能否用-memcmp-函数判断结构体相等"><a class="markdownIt-Anchor" href="#10-如何判断结构体是否相等能否用-memcmp-函数判断结构体相等"></a> 10、如何判断结构体是否相等？能否用 memcmp 函数判断结构体相等？</h2>
<p>面试高频指数：两星</p>
<hr>
<p>需要重载操作符 <code>==</code> 判断两个结构体是否相等，不能用 <code>memcmp</code> 函数判断两个结构体是否相等，因为 <code>memcmp</code> 函数是逐个字节进行比较的，而结构体在内存空间中保存时存在字节对齐，字节对齐是补的字节内容是随机的，会产生垃圾值，所以无法比较。</p>
<p>利用运算符重载来实现结构体对象的比较：</p>
<figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;iostream&gt;</span></span></span><br><span class="line"></span><br><span class="line"><span class="keyword">using</span> <span class="keyword">namespace</span> std;</span><br><span class="line"></span><br><span class="line"><span class="class"><span class="keyword">struct</span> <span class="title">A</span></span></span><br><span class="line"><span class="class">&#123;</span></span><br><span class="line">    <span class="keyword">char</span> c;</span><br><span class="line">    <span class="keyword">int</span> val;</span><br><span class="line">    <span class="built_in">A</span>(<span class="keyword">char</span> c_tmp, <span class="keyword">int</span> tmp) : <span class="built_in">c</span>(c_tmp), <span class="built_in">val</span>(tmp) &#123;&#125;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">friend</span> <span class="keyword">bool</span> <span class="keyword">operator</span>==(<span class="keyword">const</span> A &amp;tmp1, <span class="keyword">const</span> A &amp;tmp2); <span class="comment">//  友元运算符重载函数</span></span><br><span class="line">&#125;;</span><br><span class="line"></span><br><span class="line"><span class="keyword">bool</span> <span class="keyword">operator</span>==(<span class="keyword">const</span> A &amp;tmp1, <span class="keyword">const</span> A &amp;tmp2)</span><br><span class="line">&#123;</span><br><span class="line">    <span class="built_in"><span class="keyword">return</span></span> (tmp1.c == tmp2.c &amp;&amp; tmp1.val == tmp2.val);</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">int</span> <span class="title">main</span><span class="params">()</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">    <span class="function">A <span class="title">ex1</span><span class="params">(<span class="string">&#x27;a&#x27;</span>, <span class="number">90</span>)</span>, <span class="title">ex2</span><span class="params">(<span class="string">&#x27;b&#x27;</span>, <span class="number">80</span>)</span></span>;</span><br><span class="line">    <span class="keyword">if</span> (ex1 == ex2)</span><br><span class="line">        cout &lt;&lt; <span class="string">&quot;ex1 == ex2&quot;</span> &lt;&lt; endl;</span><br><span class="line">    <span class="keyword">else</span></span><br><span class="line">        cout &lt;&lt; <span class="string">&quot;ex1 != ex2&quot;</span> &lt;&lt; endl; <span class="comment">// 输出</span></span><br><span class="line">    <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<h2 id="11-参数传递时值传递-引用传递-指针传递的区别"><a class="markdownIt-Anchor" href="#11-参数传递时值传递-引用传递-指针传递的区别"></a> 11、参数传递时，值传递、引用传递、指针传递的区别？</h2>
<p>面试高频指数：两星</p>
<hr>
<p>参数传递的三种方式：</p>
<ul>
<li>
<p><strong>值传递</strong>：</p>
<p>形参是实参的拷贝，改变形参的值并不会影响外部实参的值。从被调用函数的角度来说，值传递时单向的（实参-&gt;形参），参数的值只能传入，不能传出。当函数内部需要修改参数，并且不希望这个改变影响调用者时，采用值传递。</p>
</li>
<li>
<p><strong>指针传递</strong>：</p>
<p>形参为指向实参地址的指针，当对形参的指向操作时，就相当于对实参本身进行的操作。</p>
</li>
<li>
<p><strong>引用传递</strong>：</p>
<p>形参相当于是实参的”别名“，对形参的操作其实就是对实参的操作，在引用传递过程中，被调函数的形式参数虽然也作为局部变量在栈中开辟了内存空间，但是这时存放的是由主调函数放进来的实参变量的地址。被调函数对形参的任何操作都被处理成间接寻址，即通过栈中存放的地址访问主调函数中的实参变量。正因为如此，被调函数对形参做的任何操作都影响了主调函数中的实参变量。</p>
</li>
</ul>
<p>例子：</p>
<figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="meta-keyword">include</span><span class="meta-string">&lt;iostream&gt;</span></span></span><br><span class="line"><span class="keyword">using</span> <span class="keyword">namespace</span> std;</span><br><span class="line"><span class="comment">//值传递</span></span><br><span class="line"> <span class="function"><span class="keyword">void</span> <span class="title">change1</span><span class="params">(<span class="keyword">int</span> n)</span></span>&#123;</span><br><span class="line">    cout&lt;&lt;<span class="string">&quot;值传递--函数操作地址&quot;</span>&lt;&lt;&amp;n&lt;&lt;endl;         <span class="comment">//显示的是拷贝的地址而不是源地址 </span></span><br><span class="line">    n++;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="comment">//引用传递</span></span><br><span class="line"><span class="function"><span class="keyword">void</span> <span class="title">change2</span><span class="params">(<span class="keyword">int</span> &amp; n)</span></span>&#123;</span><br><span class="line">    cout&lt;&lt;<span class="string">&quot;引用传递--函数操作地址&quot;</span>&lt;&lt;&amp;n&lt;&lt;endl; </span><br><span class="line">    n++;</span><br><span class="line">&#125;</span><br><span class="line"> <span class="comment">//指针传递</span></span><br><span class="line"><span class="function"><span class="keyword">void</span> <span class="title">change3</span><span class="params">(<span class="keyword">int</span> *n)</span></span>&#123;</span><br><span class="line">     cout&lt;&lt;<span class="string">&quot;指针传递--函数操作地址 &quot;</span>&lt;&lt;n&lt;&lt;endl; </span><br><span class="line">    *n=*n+<span class="number">1</span>;</span><br><span class="line"> &#125; </span><br><span class="line"><span class="function"><span class="keyword">int</span>     <span class="title">main</span><span class="params">()</span></span>&#123;</span><br><span class="line">    <span class="keyword">int</span> n=<span class="number">10</span>;</span><br><span class="line">    cout&lt;&lt;<span class="string">&quot;实参的地址&quot;</span>&lt;&lt;&amp;n&lt;&lt;endl;</span><br><span class="line">    <span class="built_in">change1</span>(n);</span><br><span class="line">    cout&lt;&lt;<span class="string">&quot;after change1() n=&quot;</span>&lt;&lt;n&lt;&lt;endl;</span><br><span class="line">    <span class="built_in">change2</span>(n);</span><br><span class="line">    cout&lt;&lt;<span class="string">&quot;after change2() n=&quot;</span>&lt;&lt;n&lt;&lt;endl;</span><br><span class="line">    <span class="built_in">change3</span>(&amp;n);</span><br><span class="line">    cout&lt;&lt;<span class="string">&quot;after change3() n=&quot;</span>&lt;&lt;n&lt;&lt;endl;</span><br><span class="line">    <span class="keyword">return</span> <span class="literal">true</span>;</span><br><span class="line">&#125;</span><br><span class="line"><span class="comment">/*</span></span><br><span class="line"><span class="comment">实参的地址0x28ff2c</span></span><br><span class="line"><span class="comment">值传递--函数操作地址0x28ff10</span></span><br><span class="line"><span class="comment">after change1() n=10</span></span><br><span class="line"><span class="comment">引用传递--函数操作地址0x28ff2c</span></span><br><span class="line"><span class="comment">after change2() n=11</span></span><br><span class="line"><span class="comment">指针传递--函数操作地址 0x28ff2c</span></span><br><span class="line"><span class="comment">after change3() n=12</span></span><br><span class="line"><span class="comment">*/</span></span><br></pre></td></tr></table></figure>
<p>说明：实参的地址为0x28ff2c，采用值传递的时候，函数操作的地址是0x28ff10并不是实参本身，所以对它进行操作并不能改变实参的值；再看引用传递，操作地址就是实参地址，只是相当于实参的一个别名，对它的操作就是对实参的操作；最后是指针传递，也可发现操作地址是实参地址。</p>
<p><strong>引用传递和指针传递的区别</strong>：</p>
<p><em>引用的规则：</em></p>
<ol>
<li>引用被创建的同时必须被初始化（指针则可以在任何时候被初始化）。</li>
<li>不能有 NULL 引用，引用必须与合法的存储单元关联（指针则可以是 NULL)。</li>
<li>一旦引用被初始化，就不能改变引用的关系（指针则可以随时改变所指的对象）。</li>
</ol>
<p><em>指针传递的实质：</em></p>
<p><span style="color:red"><strong>指针传递参数本质上是值传递方式，它所传递的是一个地址值。</strong></span> 值传递过程中，被调函数的形式参数作为被调函数的局部变量处理，即在栈中开辟了内存空间以存放由主调函数放进来的是参值，从而成为了实参的一个副本。值传递的特点是被调函数对形式参数的任何操作都是作为局部变量进行，不会影响主调函数的是参变量的值。（这里是在说实参指针本身的地址值不会变）。</p>
<p><strong>指针传递和引用传递一般适用于：</strong></p>
<p>函数内部修改参数并且希望改动影响调用者。对比指针/引用传递可以将改变由形参”传给“实参（实际上就是直接在实参的内存上修改，不像值传递将实参的值拷贝到另外的内存地址中才修改。</p>
<p>另一种用法：当一个函数实际需要返回多个值，而只能显式返回一个值时，可以将另外需要返回的变量以指针/引用传递给函数，这样在函数内部修改并且返回后，调用者可以拿到被修改过后的变量，也相当于一个隐式的返回值传递吧。</p>
<p>更多内容可参考：<a target="_blank" rel="noopener" href="http://xinklabi.iteye.com/blog/653643">http://xinklabi.iteye.com/blog/653643</a></p>
<h2 id="12-什么是模板如何实现"><a class="markdownIt-Anchor" href="#12-什么是模板如何实现"></a> 12、什么是模板？如何实现？</h2>
<p>面试高频指数：三星</p>
<hr>
<p>模板：创建类或者函数的蓝图或者公式，分为函数模板和类模板。</p>
<p>实现方式：模板定义以关键字 <code>template</code> 开始，后跟一个模板参数列表。</p>
<ul>
<li>模板参数列表不能为空；</li>
<li>模板类型参数前必须使用关键字 <code>class</code> 或者 <code>typename</code>，在模板参数列表中这两个关键字含义相同，可互换使用。</li>
</ul>
<figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">template</span> &lt;<span class="keyword">typename</span> T, <span class="keyword">typename</span> U, ...&gt;</span><br></pre></td></tr></table></figure>
<p>函数模板：通过定义一个函数模板，可以避免为每一种类型定义一个新函数。</p>
<ul>
<li>对于函数模板而言，模板类型参数可以用来指定返回类型或函数的参数类型，以及在函数体内用于变量声明或类型转换。</li>
<li>函数模板实例化：当调用一个模板时，编译器用函数实参来推断模板实参，从而使用实参的类型来确定绑定到模板参数的类型。</li>
</ul>
<figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="meta-keyword">include</span><span class="meta-string">&lt;iostream&gt;</span></span></span><br><span class="line"></span><br><span class="line"><span class="keyword">using</span> <span class="keyword">namespace</span> std;</span><br><span class="line"></span><br><span class="line"><span class="keyword">template</span> &lt;<span class="keyword">typename</span> T&gt;</span><br><span class="line"><span class="function">T <span class="title">add_fun</span><span class="params">(<span class="keyword">const</span> T &amp; tmp1, <span class="keyword">const</span> T &amp; tmp2)</span></span>&#123;</span><br><span class="line">    <span class="keyword">return</span> tmp1 + tmp2;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">int</span> <span class="title">main</span><span class="params">()</span></span>&#123;</span><br><span class="line">    <span class="keyword">int</span> var1, var2;</span><br><span class="line">    cin &gt;&gt; var1 &gt;&gt; var2;</span><br><span class="line">    cout &lt;&lt; <span class="built_in">add_fun</span>(var1, var2);</span><br><span class="line"></span><br><span class="line">    <span class="keyword">double</span> var3, var4;</span><br><span class="line">    cin &gt;&gt; var3 &gt;&gt; var4;</span><br><span class="line">    cout &lt;&lt; <span class="built_in">add_fun</span>(var3, var4);</span><br><span class="line">    <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>类模板：类似函数模板，类模板以关键字 <code>template</code> 开始，后跟模板参数列表。但是，编译器不能为类模板推断模板参数类型，需要在使用该类模板时，在模板名后面的尖括号中指明类型。</p>
<figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;iostream&gt;</span></span></span><br><span class="line"></span><br><span class="line"><span class="keyword">using</span> <span class="keyword">namespace</span> std;</span><br><span class="line"></span><br><span class="line"><span class="keyword">template</span> &lt;<span class="keyword">typename</span> T&gt;</span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Complex</span></span></span><br><span class="line"><span class="class">&#123;</span></span><br><span class="line"><span class="keyword">public</span>:</span><br><span class="line">    <span class="comment">//构造函数</span></span><br><span class="line">    <span class="built_in">Complex</span>(T a, T b)</span><br><span class="line">    &#123;</span><br><span class="line">        <span class="keyword">this</span>-&gt;a = a;</span><br><span class="line">        <span class="keyword">this</span>-&gt;b = b;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="comment">//运算符重载</span></span><br><span class="line">    Complex&lt;T&gt; <span class="keyword">operator</span>+(Complex &amp;c)</span><br><span class="line">    &#123;</span><br><span class="line">        <span class="function">Complex&lt;T&gt; <span class="title">tmp</span><span class="params">(<span class="keyword">this</span>-&gt;a + c.a, <span class="keyword">this</span>-&gt;b + c.b)</span></span>;</span><br><span class="line">        cout &lt;&lt; tmp.a &lt;&lt; <span class="string">&quot; &quot;</span> &lt;&lt; tmp.b &lt;&lt; endl;</span><br><span class="line">        <span class="keyword">return</span> tmp;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">private</span>:</span><br><span class="line">    T a;</span><br><span class="line">    T b;</span><br><span class="line">&#125;;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">int</span> <span class="title">main</span><span class="params">()</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">    <span class="function">Complex&lt;<span class="keyword">int</span>&gt; <span class="title">a</span><span class="params">(<span class="number">10</span>, <span class="number">20</span>)</span></span>;</span><br><span class="line">    <span class="function">Complex&lt;<span class="keyword">int</span>&gt; <span class="title">b</span><span class="params">(<span class="number">20</span>, <span class="number">30</span>)</span></span>;</span><br><span class="line">    Complex&lt;<span class="keyword">int</span>&gt; c = a + b;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<h2 id="13-函数模板和类模板的区别"><a class="markdownIt-Anchor" href="#13-函数模板和类模板的区别"></a> 13、函数模板和类模板的区别？</h2>
<p>面试高频指数：两星</p>
<hr>
<ul>
<li>实例化方式不同：函数模板实例化由编译程序在处理函数调用时自动完成，类模板实例化需要在程序中显式指定。</li>
<li>实例化的结果不同：函数模板实例化后是一个函数，类模板实例化后是一个类。</li>
<li>默认参数：类模板在模板参数列表中可以有默认参数。</li>
<li>特化：函数模板只能全特化，而类模板可以全特化，也可以偏特化。</li>
<li>调用方式不同：函数模板可以隐式调用，也可以显式调用；类模板只能显式调用。</li>
</ul>
<p>函数模板调用方式举例：</p>
<figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="meta-keyword">include</span><span class="meta-string">&lt;iostream&gt;</span></span></span><br><span class="line"></span><br><span class="line"><span class="keyword">using</span> <span class="keyword">namespace</span> std;</span><br><span class="line"></span><br><span class="line"><span class="keyword">template</span> &lt;<span class="keyword">typename</span> T&gt;</span><br><span class="line"><span class="function">T <span class="title">add_fun</span><span class="params">(<span class="keyword">const</span> T &amp; tmp1, <span class="keyword">const</span> T &amp; tmp2)</span></span>&#123;</span><br><span class="line">    <span class="keyword">return</span> tmp1 + tmp2;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">int</span> <span class="title">main</span><span class="params">()</span></span>&#123;</span><br><span class="line">    <span class="keyword">int</span> var1, var2;</span><br><span class="line">    cin &gt;&gt; var1 &gt;&gt; var2;</span><br><span class="line">    cout &lt;&lt; add_fun&lt;<span class="keyword">int</span>&gt;(var1, var2); <span class="comment">// 显式调用</span></span><br><span class="line"></span><br><span class="line">    <span class="keyword">double</span> var3, var4;</span><br><span class="line">    cin &gt;&gt; var3 &gt;&gt; var4;</span><br><span class="line">    cout &lt;&lt; <span class="built_in">add_fun</span>(var3, var4); <span class="comment">// 隐式调用</span></span><br><span class="line">    <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<h2 id="14-什么是可变参数模板"><a class="markdownIt-Anchor" href="#14-什么是可变参数模板"></a> 14、什么是可变参数模板？</h2>
<p>面试高频指数：1星</p>
<hr>
<p>可变参数模板：接受可变数目参数的模板函数或者模板类。将可变数目的参数称为参数包，包括模板参数和函数参数包。</p>
<ul>
<li>模板参数包：表示零个或多个模板参数；</li>
<li>函数参数包：表示零个或多个函数参数。</li>
</ul>
<p>用省略号来指出一个模板参数或者函数参数表示一个包，在模板参数列表中，<code>class...</code> 或 <code>typename...</code> 指出接下来的参数表示零个或多个类型的列表；一个类型名后面跟一个省略号表示零个或多个给定类型的非类型参数的列表。当需要知道包中有多少元素时，可以使用<code>sizeof...</code>运算符。</p>
<figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">template</span> &lt;<span class="keyword">typename</span> T, <span class="keyword">typename</span>... Args&gt; <span class="comment">// Args 是模板参数包</span></span><br><span class="line"><span class="function"><span class="keyword">void</span> <span class="title">foo</span><span class="params">(<span class="keyword">const</span> T &amp;t, <span class="keyword">const</span> Args&amp;... rest)</span></span>; <span class="comment">// 可变参数模板，rest 是函数参数包</span></span><br></pre></td></tr></table></figure>
<p>实例：</p>
<figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;iostream&gt;</span></span></span><br><span class="line"></span><br><span class="line"><span class="keyword">using</span> <span class="keyword">namespace</span> std;</span><br><span class="line"></span><br><span class="line"><span class="keyword">template</span> &lt;<span class="keyword">typename</span> T&gt;</span><br><span class="line"><span class="function"><span class="keyword">void</span> <span class="title">print_fun</span><span class="params">(<span class="keyword">const</span> T &amp;t)</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">    cout &lt;&lt; t &lt;&lt; endl; <span class="comment">// 最后一个元素</span></span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">template</span> &lt;<span class="keyword">typename</span> T, <span class="keyword">typename</span>... Args&gt;</span><br><span class="line"><span class="function"><span class="keyword">void</span> <span class="title">print_fun</span><span class="params">(<span class="keyword">const</span> T &amp;t, <span class="keyword">const</span> Args &amp;...args)</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">    cout &lt;&lt; t &lt;&lt; <span class="string">&quot; &quot;</span>;</span><br><span class="line">    <span class="built_in">print_fun</span>(args...);</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">int</span> <span class="title">main</span><span class="params">()</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">    <span class="built_in">print_fun</span>(<span class="string">&quot;Hello&quot;</span>, <span class="string">&quot;wolrd&quot;</span>, <span class="string">&quot;!&quot;</span>);</span><br><span class="line">    <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">&#125;</span><br><span class="line"><span class="comment">/*运行结果：</span></span><br><span class="line"><span class="comment">Hello wolrd !</span></span><br><span class="line"><span class="comment"></span></span><br><span class="line"><span class="comment">*/</span></span><br></pre></td></tr></table></figure>
<p>说明：可变参数函数通常是递归的，第一个版本的<code>print_fun</code>负责终止递归并打印初始调用中的最后一个实参。第二个版本的<code>print_fun</code>是可变参数版本，打印绑定到 <code>t</code> 的实参，并用来调用自身来打印函数参数包中的剩余值。</p>
<h2 id="15-什么是模板特化为什么特化"><a class="markdownIt-Anchor" href="#15-什么是模板特化为什么特化"></a> 15、什么是模板特化？为什么特化？</h2>
<p>面试高频指数：三星</p>
<hr>
<p>模板特化的原因：模板并非对任何模板实参都合适、都能实例化，某些情况下，通用模板的定义对特定类型不合适，可能会编译失败，或者得不到正确的结果。因此，当不希望使用模板版本时，可以定义类或者函数模板的一个特例化版本。</p>
<p>模板特化：模板参数在某种特定类型下的具体实现。分为函数模板特化和类模板特化。</p>
<ul>
<li>函数模板特化：将函数模板中的全部类型进行特例化，称为函数模板特化。</li>
<li>类模板特化：将类模板中的部分或全部类型进行特例化，称为类模板特化。</li>
</ul>
<p>特化分为全特化和偏特化：</p>
<ul>
<li>全特化：模板中的模板参数全部特例化。</li>
<li>偏特化：模板中的模板参数只确定了一部分，剩余部分需要在编译器编译时确定。</li>
</ul>
<p>说明：要区分下函数重载与函数模板特化</p>
<p>定义函数模板的特化版本，本质上是接管了编译器的工作，为原函数模板定义了一个特殊实例，而不是函数重载，函数模板特化并不影响函数匹配。</p>
<p>实例：</p>
<figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;iostream&gt;</span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;cstring&gt;</span></span></span><br><span class="line"></span><br><span class="line"><span class="keyword">using</span> <span class="keyword">namespace</span> std;</span><br><span class="line"><span class="comment">//函数模板</span></span><br><span class="line"><span class="keyword">template</span> &lt;<span class="class"><span class="keyword">class</span> <span class="title">T</span>&gt;</span></span><br><span class="line"><span class="function"><span class="keyword">bool</span> <span class="title">compare</span><span class="params">(T t1, T t2)</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">    cout &lt;&lt; <span class="string">&quot;通用版本：&quot;</span>;</span><br><span class="line">    <span class="keyword">return</span> t1 == t2;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">template</span> &lt;&gt; <span class="comment">//函数模板特化</span></span><br><span class="line"><span class="function"><span class="keyword">bool</span> <span class="title">compare</span><span class="params">(<span class="keyword">char</span> *t1, <span class="keyword">char</span> *t2)</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">    cout &lt;&lt; <span class="string">&quot;特化版本：&quot;</span>;</span><br><span class="line">    <span class="keyword">return</span> <span class="built_in">strcmp</span>(t1, t2) == <span class="number">0</span>;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">int</span> <span class="title">main</span><span class="params">(<span class="keyword">int</span> argc, <span class="keyword">char</span> *argv[])</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">    <span class="keyword">char</span> arr1[] = <span class="string">&quot;hello&quot;</span>;</span><br><span class="line">    <span class="keyword">char</span> arr2[] = <span class="string">&quot;abc&quot;</span>;</span><br><span class="line">    cout &lt;&lt; <span class="built_in">compare</span>(<span class="number">123</span>, <span class="number">123</span>) &lt;&lt; endl;</span><br><span class="line">    cout &lt;&lt; <span class="built_in">compare</span>(arr1, arr2) &lt;&lt; endl;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">&#125;</span><br><span class="line"><span class="comment">/*</span></span><br><span class="line"><span class="comment">运行结果：</span></span><br><span class="line"><span class="comment">通用版本：1</span></span><br><span class="line"><span class="comment">特化版本：0</span></span><br><span class="line"><span class="comment">*/</span></span><br></pre></td></tr></table></figure>
<h2 id="16-include-和-的区别"><a class="markdownIt-Anchor" href="#16-include-和-的区别"></a> 16、include “” 和 &lt;&gt; 的区别</h2>
<p>面试高频指数：1星</p>
<hr>
<p><code>include&lt;文件名&gt;</code> 和 <code>#include&quot;文件名&quot;</code>的区别：</p>
<ul>
<li><strong>查找文件的位置：</strong><code>include&lt;文件名&gt;</code> 在标准库头文件所在的目录中查找，如果没有，再到当前源文件所在目录下查找；<code>#include&quot;文件名&quot;</code> 在当前源文件所在目录中进行查找，如果没有，再到系统目录中查找。</li>
<li><strong>使用习惯：</strong> 对于标准库中的头文件常用 <code>include&lt;文件名&gt;</code>，对于自己定义的头文件，常用<code>#include&quot;文件名&quot;</code></li>
</ul>
<h2 id="17-switch-的-case-里为何不能定义变量"><a class="markdownIt-Anchor" href="#17-switch-的-case-里为何不能定义变量"></a> 17、switch 的 case 里为何不能定义变量</h2>
<p>面试高频指数：1星</p>
<hr>
<ul>
<li><code>switch</code> 下面的这个花括号表示一块作用域，而不是每一个 <code>case</code> 表示一块作用域。如果在某一 <code>case</code> 中定义了变量，其作用域在这块花括号内，按理说在另一个 <code>case</code> 内可以使用该变量，但是在实际使用时，每一个 <code>case</code> 之间互不影响，是相对封闭的，参考如下实例。</li>
</ul>
<p>实例：</p>
<p>下述代码中，在 <code>switch</code> 的 <code>case</code> 中定义的变量，没有实际意义，仅为了解释上述原因。</p>
<figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;iostream&gt;</span></span></span><br><span class="line"><span class="keyword">using</span> <span class="keyword">namespace</span> std;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">int</span> <span class="title">main</span><span class="params">()</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">    <span class="comment">// 局部变量声明</span></span><br><span class="line">    <span class="keyword">char</span> var = <span class="string">&#x27;D&#x27;</span>;</span><br><span class="line"></span><br><span class="line">    <span class="built_in"><span class="keyword">switch</span></span> (var)</span><br><span class="line">    &#123;</span><br><span class="line">    <span class="keyword">case</span> <span class="string">&#x27;A&#x27;</span>:</span><br><span class="line">        <span class="keyword">int</span> cnt = <span class="number">0</span>; <span class="comment">// 定义变量</span></span><br><span class="line">        cout &lt;&lt; <span class="string">&quot;Excellent.&quot;</span> &lt;&lt; endl</span><br><span class="line">             &lt;&lt; cnt;</span><br><span class="line">        <span class="keyword">break</span>;</span><br><span class="line">    <span class="keyword">case</span> <span class="string">&#x27;B&#x27;</span>:</span><br><span class="line">    <span class="keyword">case</span> <span class="string">&#x27;C&#x27;</span>:</span><br><span class="line">        ++cnt;</span><br><span class="line">        cout &lt;&lt; <span class="string">&quot;Good.&quot;</span> &lt;&lt; endl</span><br><span class="line">             &lt;&lt; cnt;</span><br><span class="line">        <span class="keyword">break</span>;</span><br><span class="line">    <span class="keyword">case</span> <span class="string">&#x27;D&#x27;</span>:</span><br><span class="line">        cout &lt;&lt; <span class="string">&quot;Not bad.&quot;</span> &lt;&lt; endl</span><br><span class="line">             &lt;&lt; cnt;</span><br><span class="line">        <span class="keyword">break</span>;</span><br><span class="line">    <span class="keyword">case</span> <span class="string">&#x27;F&#x27;</span>:</span><br><span class="line">        cout &lt;&lt; <span class="string">&quot;Bad.&quot;</span> &lt;&lt; endl</span><br><span class="line">             &lt;&lt; cnt;</span><br><span class="line">        <span class="keyword">break</span>;</span><br><span class="line">    <span class="keyword">default</span>:</span><br><span class="line">        cout &lt;&lt; <span class="string">&quot;Bad.&quot;</span> &lt;&lt; endl</span><br><span class="line">             &lt;&lt; cnt;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>简单解释：上述代码中在符合 <code>A</code> 的条件下定义了变量，当符合 <code>B</code> 或者 <code>C</code> 的条件时，对该变量进行自增操作，但是因为不符合条件 <code>A</code> 未对变量进行定义，该变量无法使用。</p>
<h2 id="18-迭代器的作用"><a class="markdownIt-Anchor" href="#18-迭代器的作用"></a> 18、迭代器的作用</h2>
<p>面试高频指数：1星</p>
<hr>
<p>迭代器：一种抽象的设计概念，在设计模式中有迭代器模式，即提供一种方法，使之能够依序寻访某个容器所含的各个元素，而无需暴露该容器的内部表述方式。</p>
<p>作用：在无需知道容器底层原理的情况下，遍历容器中的元素。</p>
<p>实例：</p>
<figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;iostream&gt;</span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;vector&gt;</span></span></span><br><span class="line"><span class="keyword">using</span> <span class="keyword">namespace</span> std;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">int</span> <span class="title">main</span><span class="params">()</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">    vector&lt;<span class="keyword">int</span>&gt; arr = &#123;<span class="number">1</span>, <span class="number">2</span>, <span class="number">3</span>, <span class="number">4</span>, <span class="number">5</span>, <span class="number">6</span>, <span class="number">7</span>, <span class="number">8</span>, <span class="number">9</span>, <span class="number">0</span>&#125;;</span><br><span class="line">    vector&lt;<span class="keyword">int</span>&gt;::iterator iter = arr.<span class="built_in">begin</span>(); <span class="comment">// 定义迭代器</span></span><br><span class="line">    <span class="keyword">for</span> (; iter != arr.<span class="built_in">end</span>(); ++iter)</span><br><span class="line">    &#123;</span><br><span class="line">        cout &lt;&lt; *iter &lt;&lt; <span class="string">&quot; &quot;</span>;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">&#125;</span><br><span class="line"><span class="comment">/*</span></span><br><span class="line"><span class="comment">运行结果：</span></span><br><span class="line"><span class="comment">1 2 3 4 5 6 7 8 9 0</span></span><br><span class="line"><span class="comment">*/</span></span><br></pre></td></tr></table></figure>
<h2 id="19-泛型编程如何实现"><a class="markdownIt-Anchor" href="#19-泛型编程如何实现"></a> 19、泛型编程如何实现？</h2>
<p>面试高频指数：两星</p>
<hr>
<p>泛型编程实现的基础：模板。模板是创建类或者函数的蓝图或者说公式，当使用一个<code>vector</code> 这样的泛型，或者 <code>find</code> 这样的泛型函数时，编译时会转化为特定的类或者函数。</p>
<p>泛型编程涉及到的知识点较广，例如：容器、迭代器、算法等都是泛型编程的实现实例。面试者可选择自己掌握比较扎实的一方面进行展开。</p>
<ul>
<li>容器：涉及到STL中的容器，例如：<code>vector</code>、<code>list</code>、<code>map</code>等，可选其中熟悉底层原理的容器进行展开讲解。</li>
<li>迭代器：在无需知道容器底层原理的情况下，遍历容器中的元素。</li>
<li>模板：可参考本章节中的模板相关问题。</li>
</ul>
<h2 id="20-什么是类型萃取"><a class="markdownIt-Anchor" href="#20-什么是类型萃取"></a> 20、什么是类型萃取？</h2>
<p>面试高频指数：1星</p>
<hr>
<p>类型萃取使用模板技术来萃取类型（包含自定义类型和内置类型）的某些特定，用以判断该类型是否含有某些特性，从而在泛型算法中来对该类型进行特殊的处理用来提高效率或者其他。</p>
<p>C++ 类型萃取一般用于模板中，当我们定义一个模板函数后，需要知道模板类型形参并加以运用时就可以用类型萃取。</p>
<p>比如我们需要在函数中进行拷贝，通常我们可以用内置函数 <code>memcpy</code> 或者自己写一个 for 循环来进行拷贝。</p>
<p><a target="_blank" rel="noopener" href="https://blog.csdn.net/xuzhangze/article/details/78374890">https://blog.csdn.net/xuzhangze/article/details/78374890</a></p>
<h1 id="七-设计模式"><a class="markdownIt-Anchor" href="#七-设计模式"></a> 七、设计模式</h1>
<h2 id="1-了解哪些设计模式"><a class="markdownIt-Anchor" href="#1-了解哪些设计模式"></a> 1、了解哪些设计模式？</h2>
<p>面试高频指数：四星</p>
<hr>
<p>《大话设计模式》一书中提到 24 种设计模式，这 24 种设计模式没必要面面俱到，但一定要深入了解其他的几种，最好结合自己在实际开发过程中的例子进行深入的了解。</p>
<p>设计模式有 6 大设计原则：</p>
<ul>
<li>单一职责原则：就一个类而言，应该仅有一个引起他变化的原因。</li>
<li>开放封闭原则：软件实体可以扩展，但是不可修改。即面对需求，对程序的改动可以通过增加代码来完成，但是不能改动现有的代码。</li>
<li>里氏代换原则：一个软件实体如果使用的是一个基类，那么一定适用于其派生类。即在软件中，把基类替换成派生类，程序的行为没有变化。</li>
<li>依赖倒转原则：抽象不应该依赖细节，细节应该依赖抽象。即针对接口编程，不要对实现编程。</li>
<li>迪米特原则：如果两个类不直接通信，那么这两个类就不应当发生直接的相互作用。如果一个类需要调用另一个类的某个方法的话，可以通过第三个类转发这个调用。</li>
<li>接口隔离原则：每个接口中不存在派生类用不到却必须实现的方法，如果不然，就要将接口拆分开，使用多个隔离的接口。</li>
</ul>
<p>设计模式分为三类：</p>
<ul>
<li>创造型模式：单例模式、工厂模式、建造者模式、原型模式</li>
<li>结构型模式：适配器模式、桥接模式、外观模式、组合模式、装饰模式、享元模式、代理模式</li>
<li>行为型模式：责任链模式、命令模式、解释器模式、迭代器模式、中介者模式、备忘录模式、观察者模式、状态模式、策略模式、模板方法模式、访问者模式</li>
</ul>
<p>下面介绍常见的几种设计模式：</p>
<ul>
<li>单例模式：保证一个类仅有一个实例，并提供一个访问它的全局访问点。</li>
<li>工厂模式：包括简单工厂模式、抽象工厂模式、工厂方法模式
<ul>
<li>简单工厂模式：主要用于创建对象。用一个工厂来根据输入的条件产生不同的类，然后根据不同类的虚函数得到不同的结果。</li>
<li>工厂方法模式：修正了简单工厂模式中不遵守开放封闭原则。把选择判断移到了客户端实现，如果想添加新功能就不用修改原来的类，直接修改客户端即可。</li>
<li>抽象工厂模式：定义了一个创建一系列相关或相互依赖的接口，而无需指定他们的具体类。</li>
</ul>
</li>
<li>观察者模式：定义了一种一对多的关系，让多个观察对象同时监听一个主题对象，主题对象发生变化时，会通知所有的观察者，使他们能够更新自己。</li>
<li>装饰模式：动态地给一个对象添加一些额外的职责，就增加功能来说，装饰模式比生成派生类更为灵活。</li>
</ul>
<h2 id="2-什么是单例模式如何实现应用场景"><a class="markdownIt-Anchor" href="#2-什么是单例模式如何实现应用场景"></a> 2、什么是单例模式？如何实现？应用场景？</h2>
<p>面试高频指数：五星</p>
<hr>
<p><strong>单例模式：</strong> 保证类的实例化对象仅有一个，并且提供一个访问它的全局访问点。</p>
<p><strong>应用场景：</strong></p>
<ul>
<li>表示文件系统的类，一个操作系统一定是只有一个文件系统，因此文件系统的类的实例有且仅有一个。</li>
<li>打印机打印程序的实例，一台计算机可以连接好几台打印机，但是计算机上的打印程序只有一个，就可以通过单例模式来避免两个打印作业同时输出到打印机。</li>
</ul>
<p><strong>实现方式：</strong></p>
<p>单例模式可以通过全局或者静态变量的形式实现，这样比较简单，但是这样会影响封装性，难以保证别的代码不会对全局变量造成影响。</p>
<ul>
<li><strong>默认的构造函数、拷贝构造函数、赋值构造函数声明为私有的</strong>，这样禁止在类的外部创建对象。</li>
<li>全局访问点也要定义成<strong>静态类型的成员变量</strong>，没有参数，返回该类的指针类型。因为使用实例化对象的时候是通过类直接调用该函数，并不是先创建一个该类的对象，通过对象调用。</li>
</ul>
<p>不安全的实现方式：</p>
<p>原因：考虑当两个线程同时调用 <code>getInstance</code> 方法，并且同时检测到 <code>instance</code> 是 <code>NULL</code>，两个线程会同时实例化对象，不符合单例模式的要求。</p>
<figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Singleton</span>&#123;</span></span><br><span class="line"><span class="keyword">private</span>:</span><br><span class="line">    <span class="keyword">static</span> Singleton * instance;</span><br><span class="line">    <span class="built_in">Singleton</span>()&#123;&#125;</span><br><span class="line">    <span class="built_in">Singleton</span>(<span class="keyword">const</span> Singleton&amp; tmp)&#123;&#125;</span><br><span class="line">    Singleton&amp; <span class="keyword">operator</span>=(<span class="keyword">const</span> Singleton&amp; tmp)&#123;&#125;</span><br><span class="line"><span class="keyword">public</span>:</span><br><span class="line">    <span class="keyword">static</span> Singleton* <span class="built_in">getInstance</span>()&#123;</span><br><span class="line">        <span class="keyword">if</span>(instance == <span class="literal">NULL</span>)&#123;</span><br><span class="line">            instance = <span class="keyword">new</span> <span class="built_in">Singleton</span>();</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">return</span> instance;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;;</span><br><span class="line">Singleton* Singleton::instance = <span class="literal">NULL</span>;</span><br></pre></td></tr></table></figure>
<p><strong>分类</strong>：</p>
<ul>
<li>懒汉模式：直到第一次用到类的实例化时才去实例化，上面是懒汉实现。</li>
<li>饿汉模式：类定义的时候就实例化。</li>
</ul>
<p>线程安全的懒汉模式实现：</p>
<p>方法：<strong>加锁</strong></p>
<p>存在的问题：每次判断实例对象是否为空，都要被锁定，如果是多线程的话，就会造成大量线程阻塞。</p>
<figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br></pre></td><td class="code"><pre><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Singleton</span>&#123;</span></span><br><span class="line"><span class="keyword">private</span>:</span><br><span class="line">    <span class="keyword">static</span> <span class="keyword">pthread_mutex_t</span> mutex;</span><br><span class="line">    <span class="keyword">static</span> Singleton * instance;</span><br><span class="line">    <span class="built_in">Singleton</span>()&#123;</span><br><span class="line">        <span class="built_in">pthread_mutex_init</span>(&amp;mutex, <span class="literal">NULL</span>); </span><br><span class="line">    &#125;</span><br><span class="line">    <span class="built_in">Singleton</span>(<span class="keyword">const</span> Singleton&amp; tmp)&#123;&#125;</span><br><span class="line">    Singleton&amp; <span class="keyword">operator</span>=(<span class="keyword">const</span> Singleton&amp; tmp)&#123;&#125;</span><br><span class="line"><span class="keyword">public</span>:</span><br><span class="line">    <span class="keyword">static</span> Singleton* <span class="built_in">getInstance</span>()&#123;</span><br><span class="line">        <span class="built_in">pthread_mutex_lock</span>(&amp;mutex);</span><br><span class="line">        <span class="keyword">if</span>(instance == <span class="literal">NULL</span>)&#123;            </span><br><span class="line">            instance = <span class="keyword">new</span> <span class="built_in">Singleton</span>();            </span><br><span class="line">        &#125;</span><br><span class="line">        <span class="built_in">pthread_mutex_unlock</span>(&amp;mutex);</span><br><span class="line">        <span class="keyword">return</span> instance;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;;</span><br><span class="line">Singleton* Singleton::instance = <span class="literal">NULL</span>;</span><br><span class="line"><span class="keyword">pthread_mutex_t</span> Singleton::mutex;</span><br></pre></td></tr></table></figure>
<p>方法：<strong>内部静态变量</strong>，在全局访问点 <code>getInstance</code> 中定义静态实例。</p>
<figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Singleton</span>&#123;</span></span><br><span class="line"><span class="keyword">private</span>:</span><br><span class="line">    <span class="keyword">static</span> <span class="keyword">pthread_mutex_t</span> mutex;</span><br><span class="line">    <span class="built_in">Singleton</span>()&#123;</span><br><span class="line">        <span class="built_in">pthread_mutex_init</span>(&amp;mutex, <span class="literal">NULL</span>);</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="built_in">Singleton</span>(<span class="keyword">const</span> Singleton&amp; temp)&#123;&#125;</span><br><span class="line">    Singleton&amp; <span class="keyword">operator</span>=(<span class="keyword">const</span> Singleton&amp; temp)&#123;&#125;</span><br><span class="line"><span class="keyword">public</span>:</span><br><span class="line">    <span class="keyword">static</span> Singleton* <span class="built_in">getInstance</span>()&#123; </span><br><span class="line">        <span class="keyword">static</span> Singleton instance;</span><br><span class="line">        <span class="keyword">return</span> &amp;instance;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;;</span><br><span class="line"><span class="keyword">pthread_mutex_t</span> Singleton::mutex; </span><br></pre></td></tr></table></figure>
<p>饿汉模式的实现：饿汉模式本身就是线程安全的不用加锁。</p>
<figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Singleton</span>&#123;</span></span><br><span class="line"><span class="keyword">private</span>:</span><br><span class="line">    <span class="keyword">static</span> Singleton* instance;</span><br><span class="line">    <span class="built_in">Singleton</span>(<span class="keyword">const</span> Singleton&amp; temp)&#123;&#125;</span><br><span class="line">    Singleton&amp; <span class="keyword">operator</span>=(<span class="keyword">const</span> Singleton&amp; temp)&#123;&#125;</span><br><span class="line"><span class="keyword">protected</span>:</span><br><span class="line">	 <span class="built_in">Singleton</span>()&#123;&#125; </span><br><span class="line"><span class="keyword">public</span>:</span><br><span class="line">    <span class="keyword">static</span> Singleton* <span class="built_in">getInstance</span>()&#123; </span><br><span class="line">        <span class="keyword">return</span> instance;    </span><br><span class="line">    &#125;</span><br><span class="line">&#125;;</span><br><span class="line">Singleton* Singleton::instance = <span class="keyword">new</span> <span class="built_in">Singleton</span>();</span><br></pre></td></tr></table></figure>
<h2 id="3-什么是工厂模式如何实现应用场景"><a class="markdownIt-Anchor" href="#3-什么是工厂模式如何实现应用场景"></a> 3、什么是工厂模式？如何实现？应用场景？</h2>
<p>面试高频指数：三星</p>
<hr>
<p>**工厂模式：**包括简单工厂模式、抽象工厂模式、工厂方法模式</p>
<ul>
<li>简单工厂模式：主要用于创建对象。用一个工厂来根据输入的条件产生不同的类，然后根据不同类的虚函数得到不同的结果。</li>
<li>工厂方法模式：修正了简单工厂模式中不遵守开发封闭原则。把选择判断移到了客户端去实现，如果想添加新功能就不用修改原来的类，直接修改客户端即可。</li>
<li>抽象工厂模式：定义了一个创建一系列相关或相互依赖的接口，而无需指定它们的具体类。</li>
</ul>
<ol>
<li>简单工厂模式</li>
</ol>
<p>主要用于创建对象。用一个工厂来根据输入的条件产生不同的类，然后根据不同类的虚函数得到不同的结果。</p>
<p><strong>应用场景：</strong></p>
<ul>
<li>适用于针对不同情况创建不同类时，只需传入工厂类的参数即可，无需了解具体实现方法。例如：计算器中对于同样的输入，执行不同的操作：加、减、乘、除。</li>
</ul>
<p><strong>实现方式：</strong></p>
<figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br><span class="line">90</span><br><span class="line">91</span><br><span class="line">92</span><br><span class="line">93</span><br><span class="line">94</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;iostream&gt;</span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;vector&gt;</span></span></span><br><span class="line"><span class="keyword">using</span> <span class="keyword">namespace</span> std;</span><br><span class="line"></span><br><span class="line"><span class="comment">// Here is the product class</span></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Operation</span></span></span><br><span class="line"><span class="class">&#123;</span></span><br><span class="line"><span class="keyword">public</span>:</span><br><span class="line">    <span class="keyword">int</span> var1, var2;</span><br><span class="line">    <span class="function"><span class="keyword">virtual</span> <span class="keyword">double</span> <span class="title">GetResult</span><span class="params">()</span></span></span><br><span class="line"><span class="function">    </span>&#123;</span><br><span class="line">        <span class="keyword">double</span> res = <span class="number">0</span>;</span><br><span class="line">        <span class="keyword">return</span> res;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;;</span><br><span class="line"></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Add_Operation</span> :</span> <span class="keyword">public</span> Operation</span><br><span class="line">&#123;</span><br><span class="line"><span class="keyword">public</span>:</span><br><span class="line">    <span class="function"><span class="keyword">virtual</span> <span class="keyword">double</span> <span class="title">GetResult</span><span class="params">()</span></span></span><br><span class="line"><span class="function">    </span>&#123;</span><br><span class="line">        <span class="keyword">return</span> var1 + var2;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;;</span><br><span class="line"></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Sub_Operation</span> :</span> <span class="keyword">public</span> Operation</span><br><span class="line">&#123;</span><br><span class="line"><span class="keyword">public</span>:</span><br><span class="line">    <span class="function"><span class="keyword">virtual</span> <span class="keyword">double</span> <span class="title">GetResult</span><span class="params">()</span></span></span><br><span class="line"><span class="function">    </span>&#123;</span><br><span class="line">        <span class="keyword">return</span> var1 - var2;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;;</span><br><span class="line"></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Mul_Operation</span> :</span> <span class="keyword">public</span> Operation</span><br><span class="line">&#123;</span><br><span class="line"><span class="keyword">public</span>:</span><br><span class="line">    <span class="function"><span class="keyword">virtual</span> <span class="keyword">double</span> <span class="title">GetResult</span><span class="params">()</span></span></span><br><span class="line"><span class="function">    </span>&#123;</span><br><span class="line">        <span class="keyword">return</span> var1 * var2;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;;</span><br><span class="line"></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Div_Operation</span> :</span> <span class="keyword">public</span> Operation</span><br><span class="line">&#123;</span><br><span class="line"><span class="keyword">public</span>:</span><br><span class="line">    <span class="function"><span class="keyword">virtual</span> <span class="keyword">double</span> <span class="title">GetResult</span><span class="params">()</span></span></span><br><span class="line"><span class="function">    </span>&#123;</span><br><span class="line">        <span class="keyword">return</span> var1 / var2;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;;</span><br><span class="line"></span><br><span class="line"><span class="comment">// Here is the Factory class</span></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Factory</span></span></span><br><span class="line"><span class="class">&#123;</span></span><br><span class="line"><span class="keyword">public</span>:</span><br><span class="line">    <span class="function"><span class="keyword">static</span> Operation *<span class="title">CreateProduct</span><span class="params">(<span class="keyword">char</span> op)</span></span></span><br><span class="line"><span class="function">    </span>&#123;</span><br><span class="line">        <span class="built_in"><span class="keyword">switch</span></span> (op)</span><br><span class="line">        &#123;</span><br><span class="line">        <span class="keyword">case</span> <span class="string">&#x27;+&#x27;</span>:</span><br><span class="line">            <span class="keyword">return</span> <span class="keyword">new</span> <span class="built_in">Add_Operation</span>();</span><br><span class="line"></span><br><span class="line">        <span class="keyword">case</span> <span class="string">&#x27;-&#x27;</span>:</span><br><span class="line">            <span class="keyword">return</span> <span class="keyword">new</span> <span class="built_in">Sub_Operation</span>();</span><br><span class="line"></span><br><span class="line">        <span class="keyword">case</span> <span class="string">&#x27;*&#x27;</span>:</span><br><span class="line">            <span class="keyword">return</span> <span class="keyword">new</span> <span class="built_in">Mul_Operation</span>();</span><br><span class="line"></span><br><span class="line">        <span class="keyword">case</span> <span class="string">&#x27;/&#x27;</span>:</span><br><span class="line">            <span class="keyword">return</span> <span class="keyword">new</span> <span class="built_in">Div_Operation</span>();</span><br><span class="line"></span><br><span class="line">        <span class="keyword">default</span>:</span><br><span class="line">            <span class="keyword">return</span> <span class="keyword">new</span> <span class="built_in">Add_Operation</span>();</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">int</span> <span class="title">main</span><span class="params">()</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">    <span class="keyword">int</span> a, b;</span><br><span class="line">    cin &gt;&gt; a &gt;&gt; b;</span><br><span class="line">    Operation *p = Factory::<span class="built_in">CreateProduct</span>(<span class="string">&#x27;+&#x27;</span>);</span><br><span class="line">    p-&gt;var1 = a;</span><br><span class="line">    p-&gt;var2 = b;</span><br><span class="line">    cout &lt;&lt; p-&gt;<span class="built_in">GetResult</span>() &lt;&lt; endl;</span><br><span class="line"></span><br><span class="line">    p = Factory::<span class="built_in">CreateProduct</span>(<span class="string">&#x27;*&#x27;</span>);</span><br><span class="line">    p-&gt;var1 = a;</span><br><span class="line">    p-&gt;var2 = b;</span><br><span class="line">    cout &lt;&lt; p-&gt;<span class="built_in">GetResult</span>() &lt;&lt; endl;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<ol start="2">
<li>工厂方法模式</li>
</ol>
<p>修正了简单工厂模式中不遵守开发封闭原则。把选择判断移到了客户端去实现，如果想添加新的功能就不用修改原来的额类，直接修改客户端即可。</p>
<p><strong>应用场景：</strong></p>
<ul>
<li>一个类不知道它锁需要的对象的类：在工厂方法模式中，客户端不需要知道具体产品类的类名，只需要知道所对应的工厂即可，具体的产品对象由具体工厂类创建；客户端需要知道具体产品的工厂类。</li>
<li>一个类通过其派生类来指定创建哪个对象：在工厂方法模式，对于抽象工厂类只需要提供一个创建产品的接口，而其派生类来确定具体要创建的对象，利用面向对象的多态性和里氏代换原则，在程序运行时，派生类对象将覆盖父类对象，从而使得系统更容易扩展。</li>
<li>将创建对象的任务委托给多个工厂派生类中的某一个，客户端在使用时可以无需关心是哪一个工厂派生类创建产品派生类，需要时再动态指定，可将具体工厂类的类名存储在配置文件或数据库中。</li>
</ul>
<p><strong>实现方式：</strong></p>
<figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br><span class="line">90</span><br><span class="line">91</span><br><span class="line">92</span><br><span class="line">93</span><br><span class="line">94</span><br><span class="line">95</span><br><span class="line">96</span><br><span class="line">97</span><br><span class="line">98</span><br><span class="line">99</span><br><span class="line">100</span><br><span class="line">101</span><br><span class="line">102</span><br><span class="line">103</span><br><span class="line">104</span><br><span class="line">105</span><br><span class="line">106</span><br><span class="line">107</span><br><span class="line">108</span><br><span class="line">109</span><br><span class="line">110</span><br><span class="line">111</span><br><span class="line">112</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;iostream&gt;</span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;vector&gt;</span></span></span><br><span class="line"><span class="keyword">using</span> <span class="keyword">namespace</span> std;</span><br><span class="line"></span><br><span class="line"><span class="comment">// Here is the product class</span></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Operation</span></span></span><br><span class="line"><span class="class">&#123;</span></span><br><span class="line"><span class="keyword">public</span>:</span><br><span class="line">    <span class="keyword">int</span> var1, var2;</span><br><span class="line">    <span class="function"><span class="keyword">virtual</span> <span class="keyword">double</span> <span class="title">GetResult</span><span class="params">()</span></span></span><br><span class="line"><span class="function">    </span>&#123;</span><br><span class="line">        <span class="keyword">double</span> res = <span class="number">0</span>;</span><br><span class="line">        <span class="keyword">return</span> res;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;;</span><br><span class="line"></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Add_Operation</span> :</span> <span class="keyword">public</span> Operation</span><br><span class="line">&#123;</span><br><span class="line"><span class="keyword">public</span>:</span><br><span class="line">    <span class="function"><span class="keyword">virtual</span> <span class="keyword">double</span> <span class="title">GetResult</span><span class="params">()</span></span></span><br><span class="line"><span class="function">    </span>&#123;</span><br><span class="line">        <span class="keyword">return</span> var1 + var2;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;;</span><br><span class="line"></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Sub_Operation</span> :</span> <span class="keyword">public</span> Operation</span><br><span class="line">&#123;</span><br><span class="line"><span class="keyword">public</span>:</span><br><span class="line">    <span class="function"><span class="keyword">virtual</span> <span class="keyword">double</span> <span class="title">GetResult</span><span class="params">()</span></span></span><br><span class="line"><span class="function">    </span>&#123;</span><br><span class="line">        <span class="keyword">return</span> var1 - var2;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;;</span><br><span class="line"></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Mul_Operation</span> :</span> <span class="keyword">public</span> Operation</span><br><span class="line">&#123;</span><br><span class="line"><span class="keyword">public</span>:</span><br><span class="line">    <span class="function"><span class="keyword">virtual</span> <span class="keyword">double</span> <span class="title">GetResult</span><span class="params">()</span></span></span><br><span class="line"><span class="function">    </span>&#123;</span><br><span class="line">        <span class="keyword">return</span> var1 * var2;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;;</span><br><span class="line"></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Div_Operation</span> :</span> <span class="keyword">public</span> Operation</span><br><span class="line">&#123;</span><br><span class="line"><span class="keyword">public</span>:</span><br><span class="line">    <span class="function"><span class="keyword">virtual</span> <span class="keyword">double</span> <span class="title">GetResult</span><span class="params">()</span></span></span><br><span class="line"><span class="function">    </span>&#123;</span><br><span class="line">        <span class="keyword">return</span> var1 / var2;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;;</span><br><span class="line"></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Factory</span></span></span><br><span class="line"><span class="class">&#123;</span></span><br><span class="line"><span class="keyword">public</span>:</span><br><span class="line">    <span class="function"><span class="keyword">virtual</span> Operation *<span class="title">CreateProduct</span><span class="params">()</span> </span>= <span class="number">0</span>;</span><br><span class="line">&#125;;</span><br><span class="line"></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Add_Factory</span> :</span> <span class="keyword">public</span> Factory</span><br><span class="line">&#123;</span><br><span class="line"><span class="keyword">public</span>:</span><br><span class="line">    <span class="function">Operation *<span class="title">CreateProduct</span><span class="params">()</span></span></span><br><span class="line"><span class="function">    </span>&#123;</span><br><span class="line">        <span class="keyword">return</span> <span class="keyword">new</span> <span class="built_in">Add_Operation</span>();</span><br><span class="line">    &#125;</span><br><span class="line">&#125;;</span><br><span class="line"></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Sub_Factory</span> :</span> <span class="keyword">public</span> Factory</span><br><span class="line">&#123;</span><br><span class="line"><span class="keyword">public</span>:</span><br><span class="line">    <span class="function">Operation *<span class="title">CreateProduct</span><span class="params">()</span></span></span><br><span class="line"><span class="function">    </span>&#123;</span><br><span class="line">        <span class="keyword">return</span> <span class="keyword">new</span> <span class="built_in">Sub_Operation</span>();</span><br><span class="line">    &#125;</span><br><span class="line">&#125;;</span><br><span class="line"></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Mul_Factory</span> :</span> <span class="keyword">public</span> Factory</span><br><span class="line">&#123;</span><br><span class="line"><span class="keyword">public</span>:</span><br><span class="line">    <span class="function">Operation *<span class="title">CreateProduct</span><span class="params">()</span></span></span><br><span class="line"><span class="function">    </span>&#123;</span><br><span class="line">        <span class="keyword">return</span> <span class="keyword">new</span> <span class="built_in">Mul_Operation</span>();</span><br><span class="line">    &#125;</span><br><span class="line">&#125;;</span><br><span class="line"></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Div_Factory</span> :</span> <span class="keyword">public</span> Factory</span><br><span class="line">&#123;</span><br><span class="line"><span class="keyword">public</span>:</span><br><span class="line">    <span class="function">Operation *<span class="title">CreateProduct</span><span class="params">()</span></span></span><br><span class="line"><span class="function">    </span>&#123;</span><br><span class="line">        <span class="keyword">return</span> <span class="keyword">new</span> <span class="built_in">Div_Operation</span>();</span><br><span class="line">    &#125;</span><br><span class="line">&#125;;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">int</span> <span class="title">main</span><span class="params">()</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">    <span class="keyword">int</span> a, b;</span><br><span class="line">    cin &gt;&gt; a &gt;&gt; b;</span><br><span class="line">    Add_Factory *p_fac = <span class="keyword">new</span> <span class="built_in">Add_Factory</span>();</span><br><span class="line">    Operation *p_pro = p_fac-&gt;<span class="built_in">CreateProduct</span>();</span><br><span class="line">    p_pro-&gt;var1 = a;</span><br><span class="line">    p_pro-&gt;var2 = b;</span><br><span class="line">    cout &lt;&lt; p_pro-&gt;<span class="built_in">GetResult</span>() &lt;&lt; endl;</span><br><span class="line"></span><br><span class="line">    Mul_Factory *p_fac1 = <span class="keyword">new</span> <span class="built_in">Mul_Factory</span>();</span><br><span class="line">    Operation *p_pro1 = p_fac1-&gt;<span class="built_in">CreateProduct</span>();</span><br><span class="line">    p_pro1-&gt;var1 = a;</span><br><span class="line">    p_pro1-&gt;var2 = b;</span><br><span class="line">    cout &lt;&lt; p_pro1-&gt;<span class="built_in">GetResult</span>() &lt;&lt; endl;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<ol start="3">
<li>抽象工厂模式</li>
</ol>
<p>定义了一个创建一系列相关或相互依赖的接口，而无需指定它们的具体类。</p>
<p><strong>应用场景：</strong></p>
<ul>
<li>一个系统不应当依赖于产品类实例如何被创建、组合和表达的细节，这对于所有类型的工厂模式都是重要的。</li>
<li>系统中有多于一个的产品族，而每次只使用其中某一产品族。</li>
<li>属于同一个产品族的产品将在一起使用，这一约束必须在系统的设计中体现出来。</li>
<li>产品等级结构稳定，设计完成之后，不会向系统中增加新的产品等级结构或者删除已有的产品等级结构。</li>
</ul>
<p><strong>实现方式：</strong></p>
<figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br><span class="line">90</span><br><span class="line">91</span><br><span class="line">92</span><br><span class="line">93</span><br><span class="line">94</span><br><span class="line">95</span><br><span class="line">96</span><br><span class="line">97</span><br><span class="line">98</span><br><span class="line">99</span><br><span class="line">100</span><br><span class="line">101</span><br><span class="line">102</span><br><span class="line">103</span><br><span class="line">104</span><br><span class="line">105</span><br><span class="line">106</span><br><span class="line">107</span><br><span class="line">108</span><br><span class="line">109</span><br><span class="line">110</span><br><span class="line">111</span><br><span class="line">112</span><br><span class="line">113</span><br><span class="line">114</span><br><span class="line">115</span><br><span class="line">116</span><br><span class="line">117</span><br><span class="line">118</span><br><span class="line">119</span><br><span class="line">120</span><br><span class="line">121</span><br><span class="line">122</span><br><span class="line">123</span><br><span class="line">124</span><br><span class="line">125</span><br><span class="line">126</span><br><span class="line">127</span><br><span class="line">128</span><br><span class="line">129</span><br><span class="line">130</span><br><span class="line">131</span><br><span class="line">132</span><br><span class="line">133</span><br><span class="line">134</span><br><span class="line">135</span><br><span class="line">136</span><br><span class="line">137</span><br><span class="line">138</span><br><span class="line">139</span><br><span class="line">140</span><br><span class="line">141</span><br><span class="line">142</span><br><span class="line">143</span><br><span class="line">144</span><br><span class="line">145</span><br><span class="line">146</span><br><span class="line">147</span><br><span class="line">148</span><br><span class="line">149</span><br><span class="line">150</span><br><span class="line">151</span><br><span class="line">152</span><br><span class="line">153</span><br><span class="line">154</span><br><span class="line">155</span><br><span class="line">156</span><br><span class="line">157</span><br><span class="line">158</span><br><span class="line">159</span><br><span class="line">160</span><br><span class="line">161</span><br><span class="line">162</span><br><span class="line">163</span><br><span class="line">164</span><br><span class="line">165</span><br><span class="line">166</span><br><span class="line">167</span><br><span class="line">168</span><br><span class="line">169</span><br><span class="line">170</span><br><span class="line">171</span><br><span class="line">172</span><br><span class="line">173</span><br><span class="line">174</span><br><span class="line">175</span><br><span class="line">176</span><br><span class="line">177</span><br><span class="line">178</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;iostream&gt;</span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;vector&gt;</span></span></span><br><span class="line"><span class="keyword">using</span> <span class="keyword">namespace</span> std;</span><br><span class="line"></span><br><span class="line"><span class="comment">// Here is the product class</span></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Operation_Pos</span></span></span><br><span class="line"><span class="class">&#123;</span></span><br><span class="line"><span class="keyword">public</span>:</span><br><span class="line">    <span class="keyword">int</span> var1, var2;</span><br><span class="line">    <span class="function"><span class="keyword">virtual</span> <span class="keyword">double</span> <span class="title">GetResult</span><span class="params">()</span></span></span><br><span class="line"><span class="function">    </span>&#123;</span><br><span class="line">        <span class="keyword">double</span> res = <span class="number">0</span>;</span><br><span class="line">        <span class="keyword">return</span> res;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;;</span><br><span class="line"></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Add_Operation_Pos</span> :</span> <span class="keyword">public</span> Operation_Pos</span><br><span class="line">&#123;</span><br><span class="line"><span class="keyword">public</span>:</span><br><span class="line">    <span class="function"><span class="keyword">virtual</span> <span class="keyword">double</span> <span class="title">GetResult</span><span class="params">()</span></span></span><br><span class="line"><span class="function">    </span>&#123;</span><br><span class="line">        <span class="keyword">return</span> var1 + var2;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;;</span><br><span class="line"></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Sub_Operation_Pos</span> :</span> <span class="keyword">public</span> Operation_Pos</span><br><span class="line">&#123;</span><br><span class="line"><span class="keyword">public</span>:</span><br><span class="line">    <span class="function"><span class="keyword">virtual</span> <span class="keyword">double</span> <span class="title">GetResult</span><span class="params">()</span></span></span><br><span class="line"><span class="function">    </span>&#123;</span><br><span class="line">        <span class="keyword">return</span> var1 - var2;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;;</span><br><span class="line"></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Mul_Operation_Pos</span> :</span> <span class="keyword">public</span> Operation_Pos</span><br><span class="line">&#123;</span><br><span class="line"><span class="keyword">public</span>:</span><br><span class="line">    <span class="function"><span class="keyword">virtual</span> <span class="keyword">double</span> <span class="title">GetResult</span><span class="params">()</span></span></span><br><span class="line"><span class="function">    </span>&#123;</span><br><span class="line">        <span class="keyword">return</span> var1 * var2;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;;</span><br><span class="line"></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Div_Operation_Pos</span> :</span> <span class="keyword">public</span> Operation_Pos</span><br><span class="line">&#123;</span><br><span class="line"><span class="keyword">public</span>:</span><br><span class="line">    <span class="function"><span class="keyword">virtual</span> <span class="keyword">double</span> <span class="title">GetResult</span><span class="params">()</span></span></span><br><span class="line"><span class="function">    </span>&#123;</span><br><span class="line">        <span class="keyword">return</span> var1 / var2;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;;</span><br><span class="line"><span class="comment">/*********************************************************************************/</span></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Operation_Neg</span></span></span><br><span class="line"><span class="class">&#123;</span></span><br><span class="line"><span class="keyword">public</span>:</span><br><span class="line">    <span class="keyword">int</span> var1, var2;</span><br><span class="line">    <span class="function"><span class="keyword">virtual</span> <span class="keyword">double</span> <span class="title">GetResult</span><span class="params">()</span></span></span><br><span class="line"><span class="function">    </span>&#123;</span><br><span class="line">        <span class="keyword">double</span> res = <span class="number">0</span>;</span><br><span class="line">        <span class="keyword">return</span> res;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;;</span><br><span class="line"></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Add_Operation_Neg</span> :</span> <span class="keyword">public</span> Operation_Neg</span><br><span class="line">&#123;</span><br><span class="line"><span class="keyword">public</span>:</span><br><span class="line">    <span class="function"><span class="keyword">virtual</span> <span class="keyword">double</span> <span class="title">GetResult</span><span class="params">()</span></span></span><br><span class="line"><span class="function">    </span>&#123;</span><br><span class="line">        <span class="keyword">return</span> -(var1 + var2);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;;</span><br><span class="line"></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Sub_Operation_Neg</span> :</span> <span class="keyword">public</span> Operation_Neg</span><br><span class="line">&#123;</span><br><span class="line"><span class="keyword">public</span>:</span><br><span class="line">    <span class="function"><span class="keyword">virtual</span> <span class="keyword">double</span> <span class="title">GetResult</span><span class="params">()</span></span></span><br><span class="line"><span class="function">    </span>&#123;</span><br><span class="line">        <span class="keyword">return</span> -(var1 - var2);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;;</span><br><span class="line"></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Mul_Operation_Neg</span> :</span> <span class="keyword">public</span> Operation_Neg</span><br><span class="line">&#123;</span><br><span class="line"><span class="keyword">public</span>:</span><br><span class="line">    <span class="function"><span class="keyword">virtual</span> <span class="keyword">double</span> <span class="title">GetResult</span><span class="params">()</span></span></span><br><span class="line"><span class="function">    </span>&#123;</span><br><span class="line">        <span class="keyword">return</span> -(var1 * var2);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;;</span><br><span class="line"></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Div_Operation_Neg</span> :</span> <span class="keyword">public</span> Operation_Neg</span><br><span class="line">&#123;</span><br><span class="line"><span class="keyword">public</span>:</span><br><span class="line">    <span class="function"><span class="keyword">virtual</span> <span class="keyword">double</span> <span class="title">GetResult</span><span class="params">()</span></span></span><br><span class="line"><span class="function">    </span>&#123;</span><br><span class="line">        <span class="keyword">return</span> -(var1 / var2);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;;</span><br><span class="line"><span class="comment">/*****************************************************************************************************/</span></span><br><span class="line"></span><br><span class="line"><span class="comment">// Here is the Factory class</span></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Factory</span></span></span><br><span class="line"><span class="class">&#123;</span></span><br><span class="line"><span class="keyword">public</span>:</span><br><span class="line">    <span class="function"><span class="keyword">virtual</span> Operation_Pos *<span class="title">CreateProduct_Pos</span><span class="params">()</span> </span>= <span class="number">0</span>;</span><br><span class="line">    <span class="function"><span class="keyword">virtual</span> Operation_Neg *<span class="title">CreateProduct_Neg</span><span class="params">()</span> </span>= <span class="number">0</span>;</span><br><span class="line">&#125;;</span><br><span class="line"></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Add_Factory</span> :</span> <span class="keyword">public</span> Factory</span><br><span class="line">&#123;</span><br><span class="line"><span class="keyword">public</span>:</span><br><span class="line">    <span class="function">Operation_Pos *<span class="title">CreateProduct_Pos</span><span class="params">()</span></span></span><br><span class="line"><span class="function">    </span>&#123;</span><br><span class="line">        <span class="keyword">return</span> <span class="keyword">new</span> <span class="built_in">Add_Operation_Pos</span>();</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="function">Operation_Neg *<span class="title">CreateProduct_Neg</span><span class="params">()</span></span></span><br><span class="line"><span class="function">    </span>&#123;</span><br><span class="line">        <span class="keyword">return</span> <span class="keyword">new</span> <span class="built_in">Add_Operation_Neg</span>();</span><br><span class="line">    &#125;</span><br><span class="line">&#125;;</span><br><span class="line"></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Sub_Factory</span> :</span> <span class="keyword">public</span> Factory</span><br><span class="line">&#123;</span><br><span class="line"><span class="keyword">public</span>:</span><br><span class="line">    <span class="function">Operation_Pos *<span class="title">CreateProduct_Pos</span><span class="params">()</span></span></span><br><span class="line"><span class="function">    </span>&#123;</span><br><span class="line">        <span class="keyword">return</span> <span class="keyword">new</span> <span class="built_in">Sub_Operation_Pos</span>();</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="function">Operation_Neg *<span class="title">CreateProduct_Neg</span><span class="params">()</span></span></span><br><span class="line"><span class="function">    </span>&#123;</span><br><span class="line">        <span class="keyword">return</span> <span class="keyword">new</span> <span class="built_in">Sub_Operation_Neg</span>();</span><br><span class="line">    &#125;</span><br><span class="line">&#125;;</span><br><span class="line"></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Mul_Factory</span> :</span> <span class="keyword">public</span> Factory</span><br><span class="line">&#123;</span><br><span class="line"><span class="keyword">public</span>:</span><br><span class="line">    <span class="function">Operation_Pos *<span class="title">CreateProduct_Pos</span><span class="params">()</span></span></span><br><span class="line"><span class="function">    </span>&#123;</span><br><span class="line">        <span class="keyword">return</span> <span class="keyword">new</span> <span class="built_in">Mul_Operation_Pos</span>();</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="function">Operation_Neg *<span class="title">CreateProduct_Neg</span><span class="params">()</span></span></span><br><span class="line"><span class="function">    </span>&#123;</span><br><span class="line">        <span class="keyword">return</span> <span class="keyword">new</span> <span class="built_in">Mul_Operation_Neg</span>();</span><br><span class="line">    &#125;</span><br><span class="line">&#125;;</span><br><span class="line"></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Div_Factory</span> :</span> <span class="keyword">public</span> Factory</span><br><span class="line">&#123;</span><br><span class="line"><span class="keyword">public</span>:</span><br><span class="line">    <span class="function">Operation_Pos *<span class="title">CreateProduct_Pos</span><span class="params">()</span></span></span><br><span class="line"><span class="function">    </span>&#123;</span><br><span class="line">        <span class="keyword">return</span> <span class="keyword">new</span> <span class="built_in">Div_Operation_Pos</span>();</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="function">Operation_Neg *<span class="title">CreateProduct_Neg</span><span class="params">()</span></span></span><br><span class="line"><span class="function">    </span>&#123;</span><br><span class="line">        <span class="keyword">return</span> <span class="keyword">new</span> <span class="built_in">Div_Operation_Neg</span>();</span><br><span class="line">    &#125;</span><br><span class="line">&#125;;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">int</span> <span class="title">main</span><span class="params">()</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">    <span class="keyword">int</span> a, b;</span><br><span class="line">    cin &gt;&gt; a &gt;&gt; b;</span><br><span class="line">    Add_Factory *p_fac = <span class="keyword">new</span> <span class="built_in">Add_Factory</span>();</span><br><span class="line">    Operation_Pos *p_pro = p_fac-&gt;<span class="built_in">CreateProduct_Pos</span>();</span><br><span class="line">    p_pro-&gt;var1 = a;</span><br><span class="line">    p_pro-&gt;var2 = b;</span><br><span class="line">    cout &lt;&lt; p_pro-&gt;<span class="built_in">GetResult</span>() &lt;&lt; endl;</span><br><span class="line"></span><br><span class="line">    Add_Factory *p_fac1 = <span class="keyword">new</span> <span class="built_in">Add_Factory</span>();</span><br><span class="line">    Operation_Neg *p_pro1 = p_fac1-&gt;<span class="built_in">CreateProduct_Neg</span>();</span><br><span class="line">    p_pro1-&gt;var1 = a;</span><br><span class="line">    p_pro1-&gt;var2 = b;</span><br><span class="line">    cout &lt;&lt; p_pro1-&gt;<span class="built_in">GetResult</span>() &lt;&lt; endl;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>更多清晰说明，可见：<a target="_blank" rel="noopener" href="https://wiki.jikexueyuan.com/project/java-design-pattern/abstract-factory-pattern.html">https://wiki.jikexueyuan.com/project/java-design-pattern/abstract-factory-pattern.html</a></p>
<h2 id="4-什么是观察者模式如何实现应用场景"><a class="markdownIt-Anchor" href="#4-什么是观察者模式如何实现应用场景"></a> 4、什么是观察者模式？如何实现？应用场景？</h2>
<p>面试高频指数：三星</p>
<hr>
<p><strong>观察者模式：</strong> 定义一种一（被观察类）对多（观察类）的关系，让多个观察对象同时监听一个被观察对象，被观察对象状态发生变化时，会通知所有的观察对象，使他们能够更新自己的状态。</p>
<p><strong>观察者模式中存在两种角色：</strong></p>
<ul>
<li>观察者：内部包含被观察者对象，当被观察者对象的状态发生变化时，更新自己的状态。（接收通知更新状态）</li>
<li>被观察者：内部包含了所有观察者对象，当状态发生变化时通知所有的观察者更新自己的状态。（发送通知）</li>
</ul>
<p><strong>应用场景：</strong></p>
<ul>
<li>当一个对象的改变需要同时改变其他对象，且不知道具体有多少对象有待改变时，应该考虑使用观察者模式。</li>
<li>一个抽象模型有两方面，其中一方面依赖与另一方面，这时可以用观察者模式将这两者封装在独立的对象中使它们各自独立地改变和复用。</li>
</ul>
<p><strong>实现方式：</strong></p>
<figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br><span class="line">90</span><br><span class="line">91</span><br><span class="line">92</span><br><span class="line">93</span><br><span class="line">94</span><br><span class="line">95</span><br><span class="line">96</span><br><span class="line">97</span><br><span class="line">98</span><br><span class="line">99</span><br><span class="line">100</span><br><span class="line">101</span><br><span class="line">102</span><br><span class="line">103</span><br><span class="line">104</span><br><span class="line">105</span><br><span class="line">106</span><br><span class="line">107</span><br><span class="line">108</span><br><span class="line">109</span><br><span class="line">110</span><br><span class="line">111</span><br><span class="line">112</span><br><span class="line">113</span><br><span class="line">114</span><br><span class="line">115</span><br><span class="line">116</span><br><span class="line">117</span><br><span class="line">118</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;iostream&gt;</span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;string&gt;</span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;list&gt;</span></span></span><br><span class="line"><span class="keyword">using</span> <span class="keyword">namespace</span> std;</span><br><span class="line"></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Subject</span>;</span></span><br><span class="line"><span class="comment">//观察者 基类 （内部实例化了被观察者的对象sub）</span></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Observer</span></span></span><br><span class="line"><span class="class">&#123;</span></span><br><span class="line"><span class="keyword">protected</span>:</span><br><span class="line">    string name;</span><br><span class="line">    Subject *sub;</span><br><span class="line"></span><br><span class="line"><span class="keyword">public</span>:</span><br><span class="line">    <span class="built_in">Observer</span>(string name, Subject *sub)</span><br><span class="line">    &#123;</span><br><span class="line">        <span class="keyword">this</span>-&gt;name = name;</span><br><span class="line">        <span class="keyword">this</span>-&gt;sub = sub;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="function"><span class="keyword">virtual</span> <span class="keyword">void</span> <span class="title">update</span><span class="params">()</span> </span>= <span class="number">0</span>;</span><br><span class="line">&#125;;</span><br><span class="line"></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">StockObserver</span> :</span> <span class="keyword">public</span> Observer</span><br><span class="line">&#123;</span><br><span class="line"><span class="keyword">public</span>:</span><br><span class="line">    <span class="built_in">StockObserver</span>(string name, Subject *sub) : <span class="built_in">Observer</span>(name, sub)</span><br><span class="line">    &#123;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="function"><span class="keyword">void</span> <span class="title">update</span><span class="params">()</span></span>;</span><br><span class="line">&#125;;</span><br><span class="line"></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">NBAObserver</span> :</span> <span class="keyword">public</span> Observer</span><br><span class="line">&#123;</span><br><span class="line"><span class="keyword">public</span>:</span><br><span class="line">    <span class="built_in">NBAObserver</span>(string name, Subject *sub) : <span class="built_in">Observer</span>(name, sub)</span><br><span class="line">    &#123;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="function"><span class="keyword">void</span> <span class="title">update</span><span class="params">()</span></span>;</span><br><span class="line">&#125;;</span><br><span class="line"><span class="comment">//被观察者 基类 （内部存放了所有的观察者对象，以便状态发生变化时，给观察者发通知）</span></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Subject</span></span></span><br><span class="line"><span class="class">&#123;</span></span><br><span class="line"><span class="keyword">protected</span>:</span><br><span class="line">    list&lt;Observer *&gt; observers;</span><br><span class="line"></span><br><span class="line"><span class="keyword">public</span>:</span><br><span class="line">    string action; <span class="comment">//被观察者对象的状态</span></span><br><span class="line">    <span class="function"><span class="keyword">virtual</span> <span class="keyword">void</span> <span class="title">attach</span><span class="params">(Observer *)</span> </span>= <span class="number">0</span>;</span><br><span class="line">    <span class="function"><span class="keyword">virtual</span> <span class="keyword">void</span> <span class="title">detach</span><span class="params">(Observer *)</span> </span>= <span class="number">0</span>;</span><br><span class="line">    <span class="function"><span class="keyword">virtual</span> <span class="keyword">void</span> <span class="title">notify</span><span class="params">()</span> </span>= <span class="number">0</span>;</span><br><span class="line">&#125;;</span><br><span class="line"></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Secretary</span> :</span> <span class="keyword">public</span> Subject</span><br><span class="line">&#123;</span><br><span class="line">    <span class="function"><span class="keyword">void</span> <span class="title">attach</span><span class="params">(Observer *observer)</span></span></span><br><span class="line"><span class="function">    </span>&#123;</span><br><span class="line">        observers.<span class="built_in">push_back</span>(observer);</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="function"><span class="keyword">void</span> <span class="title">detach</span><span class="params">(Observer *observer)</span></span></span><br><span class="line"><span class="function">    </span>&#123;</span><br><span class="line">        list&lt;Observer *&gt;::iterator iter = observers.<span class="built_in">begin</span>();</span><br><span class="line">        <span class="keyword">while</span> (iter != observers.<span class="built_in">end</span>())</span><br><span class="line">        &#123;</span><br><span class="line">            <span class="keyword">if</span> ((*iter) == observer)</span><br><span class="line">            &#123;</span><br><span class="line">                observers.<span class="built_in">erase</span>(iter);</span><br><span class="line">                <span class="keyword">return</span>;</span><br><span class="line">            &#125;</span><br><span class="line">            ++iter;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="function"><span class="keyword">void</span> <span class="title">notify</span><span class="params">()</span></span></span><br><span class="line"><span class="function">    </span>&#123;</span><br><span class="line">        list&lt;Observer *&gt;::iterator iter = observers.<span class="built_in">begin</span>();</span><br><span class="line">        <span class="keyword">while</span> (iter != observers.<span class="built_in">end</span>())</span><br><span class="line">        &#123;</span><br><span class="line">            (*iter)-&gt;<span class="built_in">update</span>();</span><br><span class="line">            ++iter;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">void</span> <span class="title">StockObserver::update</span><span class="params">()</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">    cout &lt;&lt; name &lt;&lt; <span class="string">&quot; 收到消息：&quot;</span> &lt;&lt; sub-&gt;action &lt;&lt; endl;</span><br><span class="line">    <span class="keyword">if</span> (sub-&gt;action == <span class="string">&quot;梁所长来了!&quot;</span>)</span><br><span class="line">    &#123;</span><br><span class="line">        cout &lt;&lt; <span class="string">&quot;我马上关闭股票，装做很认真工作的样子！&quot;</span> &lt;&lt; endl;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">void</span> <span class="title">NBAObserver::update</span><span class="params">()</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">    cout &lt;&lt; name &lt;&lt; <span class="string">&quot; 收到消息：&quot;</span> &lt;&lt; sub-&gt;action &lt;&lt; endl;</span><br><span class="line">    <span class="keyword">if</span> (sub-&gt;action == <span class="string">&quot;梁所长来了!&quot;</span>)</span><br><span class="line">    &#123;</span><br><span class="line">        cout &lt;&lt; <span class="string">&quot;我马上关闭NBA，装做很认真工作的样子！&quot;</span> &lt;&lt; endl;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">int</span> <span class="title">main</span><span class="params">()</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">    Subject *dwq = <span class="keyword">new</span> <span class="built_in">Secretary</span>();</span><br><span class="line">    Observer *xs = <span class="keyword">new</span> <span class="built_in">NBAObserver</span>(<span class="string">&quot;xiaoshuai&quot;</span>, dwq);</span><br><span class="line">    Observer *zy = <span class="keyword">new</span> <span class="built_in">NBAObserver</span>(<span class="string">&quot;zouyue&quot;</span>, dwq);</span><br><span class="line">    Observer *lm = <span class="keyword">new</span> <span class="built_in">StockObserver</span>(<span class="string">&quot;limin&quot;</span>, dwq);</span><br><span class="line"></span><br><span class="line">    dwq-&gt;<span class="built_in">attach</span>(xs);</span><br><span class="line">    dwq-&gt;<span class="built_in">attach</span>(zy);</span><br><span class="line">    dwq-&gt;<span class="built_in">attach</span>(lm);</span><br><span class="line"></span><br><span class="line">    dwq-&gt;action = <span class="string">&quot;去吃饭了！&quot;</span>;</span><br><span class="line">    dwq-&gt;<span class="built_in">notify</span>();</span><br><span class="line">    cout &lt;&lt; endl;</span><br><span class="line">    dwq-&gt;action = <span class="string">&quot;梁所长来了!&quot;</span>;</span><br><span class="line">    dwq-&gt;<span class="built_in">notify</span>();</span><br><span class="line">    <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<h1 id="八-参考资料"><a class="markdownIt-Anchor" href="#八-参考资料"></a> 八、参考资料</h1>
<ul>
<li>《Effective C++》</li>
<li>《More Effective C++》</li>
<li>《Visual C++ 代码参考与技巧大全》</li>
<li>《STL源码剖析》</li>
<li>《大话设计模式》</li>
<li>《设计模式：可复用面向对象软件的基础》++</li>
</ul>


      <div>
        
        <div>
    
        <div style="text-align:center;color: #ccc;font-size:14px;">-------------本文结束<i class="fa fa-paw"></i>感谢您的阅读-------------</div>
    
</div>


        
      </div>

    </div>

    
    
    
        

<div>
<ul class="post-copyright">
  <li class="post-copyright-author">
    <strong>本文作者： </strong>Maureen
  </li>
  <li class="post-copyright-link">
    <strong>本文链接：</strong>
    <a href="https://maureen-liu.gitee.io/p/1cb47e9e.html" title="C++面试突击">https://maureen-liu.gitee.io/p/1cb47e9e.html</a>
  </li>
  <li class="post-copyright-license">
    <strong>版权声明： </strong>本博客所有文章除特别声明外，均采用 <a href="https://creativecommons.org/licenses/by-nc-sa/4.0/" rel="noopener" target="_blank"><i class="fab fa-fw fa-creative-commons"></i>BY-NC-SA</a> 许可协议。转载请注明出处！
  </li>
</ul>
</div>


      <footer class="post-footer">

        


        
    <div class="post-nav">
      <div class="post-nav-item">
    <a href="/p/ae8b63c8.html" rel="prev" title="C++STL标准库与泛型编程">
      <i class="fa fa-chevron-left"></i> C++STL标准库与泛型编程
    </a></div>
      <div class="post-nav-item"></div>
    </div>
      </footer>
    
  </article>
  
  
  



          </div>
          
    <div class="comments" id="valine-comments"></div>

<script>
  window.addEventListener('tabs:register', () => {
    let { activeClass } = CONFIG.comments;
    if (CONFIG.comments.storage) {
      activeClass = localStorage.getItem('comments_active') || activeClass;
    }
    if (activeClass) {
      let activeTab = document.querySelector(`a[href="#comment-${activeClass}"]`);
      if (activeTab) {
        activeTab.click();
      }
    }
  });
  if (CONFIG.comments.storage) {
    window.addEventListener('tabs:click', event => {
      if (!event.target.matches('.tabs-comment .tab-content .tab-pane')) return;
      let commentClass = event.target.classList[1];
      localStorage.setItem('comments_active', commentClass);
    });
  }
</script>

        </div>
          
  
  <div class="toggle sidebar-toggle">
    <span class="toggle-line toggle-line-first"></span>
    <span class="toggle-line toggle-line-middle"></span>
    <span class="toggle-line toggle-line-last"></span>
  </div>

  <aside class="sidebar">
    <div class="sidebar-inner">

      <ul class="sidebar-nav motion-element">
        <li class="sidebar-nav-toc">
          文章目录
        </li>
        <li class="sidebar-nav-overview">
          站点概览
        </li>
      </ul>
        
      <!--noindex-->
      <div class="post-toc-wrap sidebar-panel">
          <div class="post-toc motion-element"><ol class="nav"><li class="nav-item nav-level-1"><a class="nav-link" href="#%E4%B8%80-%E7%BC%96%E8%AF%91%E5%86%85%E5%AD%98%E7%9B%B8%E5%85%B3"><span class="nav-text"> 一、编译内存相关</span></a><ol class="nav-child"><li class="nav-item nav-level-2"><a class="nav-link" href="#1-c-%E7%A8%8B%E5%BA%8F%E7%BC%96%E8%AF%91%E8%BF%87%E7%A8%8B"><span class="nav-text"> 1、C++ 程序编译过程</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#2-c%E5%86%85%E5%AD%98%E7%AE%A1%E7%90%86"><span class="nav-text"> 2、C++内存管理</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#3-%E6%A0%88%E5%92%8C%E5%A0%86%E7%9A%84%E5%8C%BA%E5%88%AB"><span class="nav-text"> 3、栈和堆的区别</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#4-%E5%8F%98%E9%87%8F%E7%9A%84%E5%8C%BA%E5%88%AB"><span class="nav-text"> 4、变量的区别</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#5-%E5%85%A8%E5%B1%80%E5%8F%98%E9%87%8F%E5%AE%9A%E4%B9%89%E5%9C%A8%E5%A4%B4%E6%96%87%E4%BB%B6%E4%B8%AD%E6%9C%89%E4%BB%80%E4%B9%88%E9%97%AE%E9%A2%98"><span class="nav-text"> 5、全局变量定义在头文件中有什么问题？</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#6-%E5%AF%B9%E8%B1%A1%E5%88%9B%E5%BB%BA%E9%99%90%E5%88%B6%E5%9C%A8%E5%A0%86%E6%88%96%E6%A0%88"><span class="nav-text"> 6、对象创建限制在堆或栈</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#7-%E5%86%85%E5%AD%98%E5%AF%B9%E9%BD%90"><span class="nav-text"> 7、内存对齐</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#8-%E7%B1%BB%E7%9A%84%E5%A4%A7%E5%B0%8F"><span class="nav-text"> 8、类的大小</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#9-%E4%BB%80%E4%B9%88%E6%98%AF%E5%86%85%E5%AD%98%E6%B3%84%E6%BC%8F"><span class="nav-text"> 9、什么是内存泄漏</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#10-%E6%80%8E%E4%B9%88%E9%98%B2%E6%AD%A2%E5%86%85%E5%AD%98%E6%B3%84%E6%BC%8F%E5%86%85%E5%AD%98%E6%B3%84%E6%BC%8F%E6%A3%80%E6%B5%8B%E5%B7%A5%E5%85%B7%E7%9A%84%E5%8E%9F%E7%90%86"><span class="nav-text"> 10、怎么防止内存泄漏？内存泄漏检测工具的原理？</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#11-%E6%99%BA%E8%83%BD%E6%8C%87%E9%92%88%E6%9C%89%E5%93%AA%E5%87%A0%E7%A7%8D%E6%99%BA%E8%83%BD%E6%8C%87%E9%92%88%E7%9A%84%E5%AE%9E%E7%8E%B0%E5%8E%9F%E7%90%86"><span class="nav-text"> 11、智能指针有哪几种？智能指针的实现原理？</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#12-%E4%B8%80%E4%B8%AA-unique_ptr-%E6%80%8E%E4%B9%88%E8%B5%8B%E5%80%BC%E7%BB%99%E5%8F%A6%E4%B8%80%E4%B8%AA-unique_ptr-%E5%AF%B9%E8%B1%A1"><span class="nav-text"> 12、一个 unique_ptr 怎么赋值给另一个 unique_ptr 对象？</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#13-%E4%BD%BF%E7%94%A8%E6%99%BA%E8%83%BD%E6%8C%87%E9%92%88%E4%BC%9A%E5%87%BA%E7%8E%B0%E4%BB%80%E4%B9%88%E9%97%AE%E9%A2%98%E6%80%8E%E4%B9%88%E8%A7%A3%E5%86%B3"><span class="nav-text"> 13、使用智能指针会出现什么问题？怎么解决？</span></a></li></ol></li><li class="nav-item nav-level-1"><a class="nav-link" href="#%E4%BA%8C-%E8%AF%AD%E8%A8%80%E5%AF%B9%E6%AF%94"><span class="nav-text"> 二、语言对比</span></a><ol class="nav-child"><li class="nav-item nav-level-2"><a class="nav-link" href="#1-c11-%E6%96%B0%E7%89%B9%E6%80%A7"><span class="nav-text"> 1、C++11 新特性</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#2-c%E5%92%8Cc%E7%9A%84%E5%8C%BA%E5%88%AB"><span class="nav-text"> 2、C和C++的区别</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#3-java%E5%92%8Cc%E7%9A%84%E5%8C%BA%E5%88%AB"><span class="nav-text"> 3、Java和C++的区别</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#4-python%E5%92%8Cc%E7%9A%84%E5%8C%BA%E5%88%AB"><span class="nav-text"> 4、Python和C++的区别</span></a></li></ol></li><li class="nav-item nav-level-1"><a class="nav-link" href="#%E4%B8%89-%E9%9D%A2%E5%90%91%E5%AF%B9%E8%B1%A1"><span class="nav-text"> 三、面向对象</span></a><ol class="nav-child"><li class="nav-item nav-level-2"><a class="nav-link" href="#1-%E4%BB%80%E4%B9%88%E6%98%AF%E9%9D%A2%E5%90%91%E5%AF%B9%E8%B1%A1%E9%9D%A2%E5%90%91%E5%AF%B9%E8%B1%A1%E7%9A%84%E4%B8%89%E5%A4%A7%E7%89%B9%E6%80%A7"><span class="nav-text"> 1、什么是面向对象？面向对象的三大特性</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#2-%E9%87%8D%E8%BD%BD-%E9%87%8D%E5%86%99-%E9%9A%90%E8%97%8F%E7%9A%84%E5%8C%BA%E5%88%AB"><span class="nav-text"> 2、重载、重写、隐藏的区别</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#3-%E5%A6%82%E4%BD%95%E7%90%86%E8%A7%A3-c-%E6%98%AF%E9%9D%A2%E5%90%91%E5%AF%B9%E8%B1%A1%E7%BC%96%E7%A8%8B"><span class="nav-text"> 3、如何理解 C++ 是面向对象编程</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#4-%E4%BB%80%E4%B9%88%E6%98%AF%E5%A4%9A%E6%80%81%E5%A4%9A%E6%80%81%E5%A6%82%E4%BD%95%E5%AE%9E%E7%8E%B0"><span class="nav-text"> 4、什么是多态？多态如何实现？</span></a></li></ol></li><li class="nav-item nav-level-1"><a class="nav-link" href="#%E5%9B%9B-%E5%85%B3%E9%94%AE%E5%AD%97%E5%BA%93%E5%87%BD%E6%95%B0"><span class="nav-text"> 四、关键字库函数</span></a><ol class="nav-child"><li class="nav-item nav-level-2"><a class="nav-link" href="#1-sizeof-%E5%92%8C-strlen-%E7%9A%84%E5%8C%BA%E5%88%AB"><span class="nav-text"> 1、sizeof 和 strlen 的区别</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#2-lambda-%E8%A1%A8%E8%BE%BE%E5%BC%8F%E5%8C%BF%E5%90%8D%E5%87%BD%E6%95%B0%E7%9A%84%E5%85%B7%E4%BD%93%E5%BA%94%E7%94%A8%E5%92%8C%E4%BD%BF%E7%94%A8%E5%9C%BA%E6%99%AF"><span class="nav-text"> 2、lambda 表达式（匿名函数）的具体应用和使用场景</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#3-explicit-%E7%9A%84%E4%BD%9C%E7%94%A8%E5%A6%82%E4%BD%95%E9%81%BF%E5%85%8D%E7%BC%96%E8%AF%91%E5%99%A8%E8%BF%9B%E8%A1%8C%E9%9A%90%E5%BC%8F%E7%B1%BB%E5%9E%8B%E8%BD%AC%E6%8D%A2"><span class="nav-text"> 3、explicit 的作用（如何避免编译器进行隐式类型转换）</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#4-c-%E5%92%8C-c-static%E7%9A%84%E5%8C%BA%E5%88%AB"><span class="nav-text"> 4、C 和 C++ static的区别</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#5-static-%E7%9A%84%E4%BD%9C%E7%94%A8"><span class="nav-text"> 5、static 的作用</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#6-static-%E5%9C%A8%E7%B1%BB%E4%B8%AD%E4%BD%BF%E7%94%A8%E7%9A%84%E6%B3%A8%E6%84%8F%E4%BA%8B%E9%A1%B9%E5%AE%9A%E4%B9%89-%E5%88%9D%E5%A7%8B%E5%8C%96%E5%92%8C%E4%BD%BF%E7%94%A8"><span class="nav-text"> 6、static 在类中使用的注意事项（定义、初始化和使用）</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#7-static-%E5%85%A8%E5%B1%80%E5%8F%98%E9%87%8F%E5%92%8C%E6%99%AE%E9%80%9A%E5%85%A8%E5%B1%80%E5%8F%98%E9%87%8F%E7%9A%84%E5%BC%82%E5%90%8C"><span class="nav-text"> 7、static 全局变量和普通全局变量的异同</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#8-const-%E4%BD%9C%E7%94%A8%E5%8F%8A%E7%94%A8%E6%B3%95"><span class="nav-text"> 8、const 作用及用法</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#9-define-%E5%92%8C-const-%E7%9A%84%E5%8C%BA%E5%88%AB"><span class="nav-text"> 9、define 和 const 的区别</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#10-define-%E5%92%8C-typedef-%E7%9A%84%E5%8C%BA%E5%88%AB"><span class="nav-text"> 10、define 和 typedef 的区别</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#11-%E7%94%A8%E5%AE%8F%E5%AE%9E%E7%8E%B0%E6%AF%94%E8%BE%83%E5%A4%A7%E5%B0%8F%E4%BB%A5%E5%8F%8A%E4%B8%A4%E4%B8%AA%E6%95%B0%E4%B8%AD%E7%9A%84%E6%9C%80%E5%B0%8F%E5%80%BC"><span class="nav-text"> 11、用宏实现比较大小，以及两个数中的最小值</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#12-inline-%E4%BD%9C%E7%94%A8%E5%8F%8A%E4%BD%BF%E7%94%A8%E6%96%B9%E6%B3%95"><span class="nav-text"> 12、inline 作用及使用方法</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#13-inline-%E5%87%BD%E6%95%B0%E5%B7%A5%E4%BD%9C%E5%8E%9F%E7%90%86"><span class="nav-text"> 13、inline 函数工作原理</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#14-%E5%AE%8F%E5%AE%9A%E4%B9%89define%E5%92%8C%E5%86%85%E8%81%94%E5%87%BD%E6%95%B0inline%E7%9A%84%E5%8C%BA%E5%88%AB"><span class="nav-text"> 14、宏定义（define）和内联函数（inline）的区别</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#15-new-%E7%9A%84%E4%BD%9C%E7%94%A8"><span class="nav-text"> 15、new 的作用？</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#16-new-%E5%92%8C-malloc-%E5%A6%82%E4%BD%95%E5%88%A4%E6%96%AD%E6%98%AF%E5%90%A6%E7%94%B3%E8%AF%B7%E5%88%B0%E5%86%85%E5%AD%98"><span class="nav-text"> 16、new 和 malloc 如何判断是否申请到内存？</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#17-delete-%E5%AE%9E%E7%8E%B0%E5%8E%9F%E7%90%86delete-%E5%92%8C-delete-%E7%9A%84%E5%8C%BA%E5%88%AB"><span class="nav-text"> 17、delete 实现原理？delete 和 delete[] 的区别？</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#18-new-%E5%92%8C-malloc-%E7%9A%84%E5%8C%BA%E5%88%ABdelete-%E5%92%8C-free-%E7%9A%84%E5%8C%BA%E5%88%AB"><span class="nav-text"> 18、new 和 malloc 的区别，delete 和 free 的区别</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#19-malloc%E7%9A%84%E5%8E%9F%E7%90%86malloc%E7%9A%84%E5%BA%95%E5%B1%82%E5%AE%9E%E7%8E%B0"><span class="nav-text"> 19、malloc的原理？malloc的底层实现？</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#20-c-%E5%92%8C-c-struct-%E7%9A%84%E5%8C%BA%E5%88%AB"><span class="nav-text"> 20、C 和 C++ struct 的区别？</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#21-%E4%B8%BA%E4%BB%80%E4%B9%88%E6%9C%89%E4%BA%86-class-%E8%BF%98%E4%BF%9D%E7%95%99-struct"><span class="nav-text"> 21、为什么有了 class 还保留 struct</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#22-struct-%E5%92%8C-union-%E7%9A%84%E5%8C%BA%E5%88%AB"><span class="nav-text"> 22、struct 和 union 的区别</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#23-class-%E5%92%8C-struct-%E7%9A%84%E5%BC%82%E5%90%8C"><span class="nav-text"> 23、class 和 struct 的异同</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#24-volatile-%E7%9A%84%E4%BD%9C%E7%94%A8%E6%98%AF%E5%90%A6%E5%85%B7%E6%9C%89%E5%8E%9F%E5%AD%90%E6%80%A7%E5%AF%B9%E7%BC%96%E8%AF%91%E5%99%A8%E6%9C%89%E4%BB%80%E4%B9%88%E5%BD%B1%E5%93%8D"><span class="nav-text"> 24、volatile 的作用？是否具有原子性，对编译器有什么影响？</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#25-%E4%BB%80%E4%B9%88%E6%83%85%E5%86%B5%E4%B8%8B%E4%B8%80%E5%AE%9A%E8%A6%81%E7%94%A8-volatile%E8%83%BD%E5%90%A6%E5%92%8C-const-%E4%B8%80%E8%B5%B7%E4%BD%BF%E7%94%A8"><span class="nav-text"> 25、什么情况下一定要用 volatile，能否和 const 一起使用？</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#26-%E8%BF%94%E5%9B%9E%E5%87%BD%E6%95%B0%E4%B8%AD%E9%9D%99%E6%80%81%E5%8F%98%E9%87%8F%E7%9A%84%E5%9C%B0%E5%9D%80%E4%BC%9A%E5%8F%91%E7%94%9F%E4%BB%80%E4%B9%88"><span class="nav-text"> 26、返回函数中静态变量的地址会发生什么？</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#27-extern-c-%E7%9A%84%E4%BD%9C%E7%94%A8"><span class="nav-text"> 27、extern C 的作用？</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#28-sizeof1-1-%E5%9C%A8-c-%E5%92%8C-c-%E4%B8%AD%E5%88%86%E5%88%AB%E6%98%AF%E4%BB%80%E4%B9%88%E7%BB%93%E6%9E%9C"><span class="nav-text"> 28、sizeof(1 &#x3D;&#x3D; 1) 在 C 和 C++ 中分别是什么结果？</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#29-memcpy-%E5%87%BD%E6%95%B0%E7%9A%84%E5%BA%95%E5%B1%82%E5%8E%9F%E7%90%86"><span class="nav-text"> 29、memcpy 函数的底层原理？</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#30-strcpy-%E5%87%BD%E6%95%B0%E6%9C%89%E4%BB%80%E4%B9%88%E7%BC%BA%E9%99%B7"><span class="nav-text"> 30、strcpy 函数有什么缺陷？</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#31-auto-%E7%B1%BB%E5%9E%8B%E6%8E%A8%E5%AF%BC%E7%9A%84%E5%8E%9F%E7%90%86"><span class="nav-text"> 31、auto 类型推导的原理</span></a></li></ol></li><li class="nav-item nav-level-1"><a class="nav-link" href="#%E4%BA%94-%E7%B1%BB%E7%9B%B8%E5%85%B3"><span class="nav-text"> 五、类相关</span></a><ol class="nav-child"><li class="nav-item nav-level-2"><a class="nav-link" href="#1-%E4%BB%80%E4%B9%88%E6%98%AF%E8%99%9A%E5%87%BD%E6%95%B0%E4%BB%80%E4%B9%88%E6%98%AF%E7%BA%AF%E8%99%9A%E5%87%BD%E6%95%B0"><span class="nav-text"> 1、什么是虚函数？什么是纯虚函数？</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#2-%E8%99%9A%E5%87%BD%E6%95%B0%E5%92%8C%E7%BA%AF%E8%99%9A%E5%87%BD%E6%95%B0%E7%9A%84%E5%8C%BA%E5%88%AB"><span class="nav-text"> 2、虚函数和纯虚函数的区别？</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#3-%E8%99%9A%E5%87%BD%E6%95%B0%E7%9A%84%E5%AE%9E%E7%8E%B0%E6%9C%BA%E5%88%B6"><span class="nav-text"> 3、虚函数的实现机制</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#4-%E5%8D%95%E7%BB%A7%E6%89%BF%E5%92%8C%E5%A4%9A%E7%BB%A7%E6%89%BF%E7%9A%84%E8%99%9A%E5%87%BD%E6%95%B0%E8%A1%A8%E7%BB%93%E6%9E%84"><span class="nav-text"> 4、单继承和多继承的虚函数表结构</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#5-%E5%A6%82%E4%BD%95%E7%A6%81%E6%AD%A2%E6%9E%84%E9%80%A0%E5%87%BD%E6%95%B0%E7%9A%84%E4%BD%BF%E7%94%A8"><span class="nav-text"> 5、如何禁止构造函数的使用？</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#6-%E4%BB%80%E4%B9%88%E6%98%AF%E7%B1%BB%E7%9A%84%E9%BB%98%E8%AE%A4%E6%9E%84%E9%80%A0%E5%87%BD%E6%95%B0"><span class="nav-text"> 6、什么是类的默认构造函数？</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#7-%E6%9E%84%E9%80%A0%E5%87%BD%E6%95%B0-%E6%9E%90%E6%9E%84%E5%87%BD%E6%95%B0%E6%98%AF%E5%90%A6%E9%9C%80%E8%A6%81%E5%AE%9A%E4%B9%89%E6%88%90%E8%99%9A%E5%87%BD%E6%95%B0%E4%B8%BA%E4%BB%80%E4%B9%88"><span class="nav-text"> 7、构造函数、析构函数是否需要定义成虚函数？为什么？</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#8-%E5%A6%82%E4%BD%95%E9%81%BF%E5%85%8D%E6%8B%B7%E8%B4%9D"><span class="nav-text"> 8、如何避免拷贝？</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#9-%E5%A6%82%E4%BD%95%E5%87%8F%E5%B0%91%E6%9E%84%E9%80%A0%E5%87%BD%E6%95%B0%E5%BC%80%E9%94%80"><span class="nav-text"> 9、如何减少构造函数开销？</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#10-%E5%A4%9A%E9%87%8D%E7%BB%A7%E6%89%BF%E6%97%B6%E4%BC%9A%E5%87%BA%E7%8E%B0%E4%BB%80%E4%B9%88%E7%8A%B6%E5%86%B5%E5%A6%82%E4%BD%95%E8%A7%A3%E5%86%B3"><span class="nav-text"> 10、多重继承时会出现什么状况？如何解决？</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#11-%E7%A9%BA%E7%B1%BB%E5%8D%A0%E5%A4%9A%E5%B0%91%E5%AD%97%E8%8A%82c%E7%BC%96%E8%AF%91%E5%99%A8%E4%BC%9A%E7%BB%99%E4%B8%80%E4%B8%AA%E7%A9%BA%E7%B1%BB%E8%87%AA%E5%8A%A8%E7%94%9F%E6%88%90%E5%93%AA%E4%BA%9B%E5%87%BD%E6%95%B0"><span class="nav-text"> 11、空类占多少字节？C++编译器会给一个空类自动生成哪些函数？</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#12-%E4%B8%BA%E4%BB%80%E4%B9%88%E6%8B%B7%E8%B4%9D%E6%9E%84%E9%80%A0%E5%87%BD%E6%95%B0%E5%BF%85%E9%A1%BB%E4%B8%BA%E5%BC%95%E7%94%A8"><span class="nav-text"> 12、为什么拷贝构造函数必须为引用？</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#13-c-%E7%B1%BB%E5%AF%B9%E8%B1%A1%E7%9A%84%E5%88%9D%E5%A7%8B%E5%8C%96%E9%A1%BA%E5%BA%8F"><span class="nav-text"> 13、C++ 类对象的初始化顺序</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#14-%E5%A6%82%E4%BD%95%E7%A6%81%E6%AD%A2%E4%B8%80%E4%B8%AA%E7%B1%BB%E8%A2%AB%E5%AE%9E%E4%BE%8B%E5%8C%96"><span class="nav-text"> 14、如何禁止一个类被实例化？</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#15-%E4%B8%BA%E4%BB%80%E4%B9%88%E7%94%A8%E6%88%90%E5%91%98%E5%88%9D%E5%A7%8B%E5%8C%96%E5%88%97%E8%A1%A8%E4%BC%9A%E5%BF%AB%E4%B8%80%E4%BA%9B"><span class="nav-text"> 15、为什么用成员初始化列表会快一些？</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#16-%E5%AE%9E%E4%BE%8B%E5%8C%96%E4%B8%80%E4%B8%AA%E5%AF%B9%E8%B1%A1%E9%9C%80%E8%A6%81%E5%93%AA%E5%87%A0%E4%B8%AA%E9%98%B6%E6%AE%B5"><span class="nav-text"> 16、实例化一个对象需要哪几个阶段</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#17-%E5%8F%8B%E5%85%83%E5%87%BD%E6%95%B0%E7%9A%84%E4%BD%9C%E7%94%A8%E5%8F%8A%E4%BD%BF%E7%94%A8%E5%9C%BA%E6%99%AF"><span class="nav-text"> 17、友元函数的作用及使用场景</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#18-%E9%9D%99%E6%80%81%E7%BB%91%E5%AE%9A%E5%92%8C%E5%8A%A8%E6%80%81%E7%BB%91%E5%AE%9A%E6%98%AF%E6%80%8E%E4%B9%88%E5%AE%9E%E7%8E%B0%E7%9A%84"><span class="nav-text"> 18、静态绑定和动态绑定是怎么实现的？</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#19-%E6%B7%B1%E6%8B%B7%E8%B4%9D%E5%92%8C%E6%B5%85%E6%8B%B7%E8%B4%9D%E7%9A%84%E5%8C%BA%E5%88%AB"><span class="nav-text"> 19、深拷贝和浅拷贝的区别</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#20-%E7%BC%96%E8%AF%91%E6%97%B6%E5%A4%9A%E6%80%81%E5%92%8C%E8%BF%90%E8%A1%8C%E6%97%B6%E5%A4%9A%E6%80%81%E7%9A%84%E5%8C%BA%E5%88%AB"><span class="nav-text"> 20、编译时多态和运行时多态的区别</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#21-%E5%AE%9E%E7%8E%B0%E4%B8%80%E4%B8%AA%E7%B1%BB%E6%88%90%E5%91%98%E5%87%BD%E6%95%B0%E8%A6%81%E6%B1%82%E4%B8%8D%E5%85%81%E8%AE%B8%E4%BF%AE%E6%94%B9%E7%B1%BB%E7%9A%84%E6%88%90%E5%91%98%E5%8F%98%E9%87%8F"><span class="nav-text"> 21、实现一个类成员函数，要求不允许修改类的成员变量？</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#22-%E5%A6%82%E4%BD%95%E8%AE%A9%E7%B1%BB%E4%B8%8D%E8%83%BD%E8%A2%AB%E7%BB%A7%E6%89%BF"><span class="nav-text"> 22、如何让类不能被继承？</span></a></li></ol></li><li class="nav-item nav-level-1"><a class="nav-link" href="#%E5%85%AD-%E8%AF%AD%E8%A8%80%E7%89%B9%E6%80%A7%E7%9B%B8%E5%85%B3"><span class="nav-text"> 六、语言特性相关</span></a><ol class="nav-child"><li class="nav-item nav-level-2"><a class="nav-link" href="#1-%E5%B7%A6%E5%80%BC%E5%92%8C%E5%8F%B3%E5%80%BC%E7%9A%84%E5%8C%BA%E5%88%AB%E5%B7%A6%E5%80%BC%E5%BC%95%E7%94%A8%E5%92%8C%E5%8F%B3%E5%80%BC%E5%BC%95%E7%94%A8%E7%9A%84%E5%8C%BA%E5%88%AB%E5%A6%82%E4%BD%95%E5%B0%86%E5%B7%A6%E5%80%BC%E8%BD%AC%E6%8D%A2%E6%88%90%E5%8F%B3%E5%80%BC"><span class="nav-text"> 1、左值和右值的区别？左值引用和右值引用的区别，如何将左值转换成右值？</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#2-stdmove-%E5%87%BD%E6%95%B0%E7%9A%84%E5%AE%9E%E7%8E%B0%E5%8E%9F%E7%90%86"><span class="nav-text"> 2、std::move() 函数的实现原理</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#3-%E4%BB%80%E4%B9%88%E6%98%AF%E6%8C%87%E9%92%88%E6%8C%87%E9%92%88%E7%9A%84%E5%A4%A7%E5%B0%8F%E5%8F%8A%E7%94%A8%E6%B3%95"><span class="nav-text"> 3、什么是指针？指针的大小及用法？</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#4-%E4%BB%80%E4%B9%88%E6%98%AF%E9%87%8E%E6%8C%87%E9%92%88%E5%92%8C%E6%82%AC%E7%A9%BA%E6%8C%87%E9%92%88"><span class="nav-text"> 4、什么是野指针和悬空指针？</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#5-c-11-nullptr-%E6%AF%94-null-%E4%BC%98%E5%8A%BF"><span class="nav-text"> 5、C++ 11 nullptr 比 NULL 优势</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#6-%E6%8C%87%E9%92%88%E5%92%8C%E5%BC%95%E7%94%A8%E7%9A%84%E5%8C%BA%E5%88%AB"><span class="nav-text"> 6、指针和引用的区别？</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#7-%E5%B8%B8%E9%87%8F%E6%8C%87%E9%92%88%E5%92%8C%E6%8C%87%E9%92%88%E5%B8%B8%E9%87%8F%E7%9A%84%E5%8C%BA%E5%88%AB"><span class="nav-text"> 7、常量指针和指针常量的区别</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#8-%E5%87%BD%E6%95%B0%E6%8C%87%E9%92%88%E5%92%8C%E6%8C%87%E9%92%88%E5%87%BD%E6%95%B0%E7%9A%84%E5%8C%BA%E5%88%AB"><span class="nav-text"> 8、函数指针和指针函数的区别</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#9-%E5%BC%BA%E5%88%B6%E7%B1%BB%E5%9E%8B%E8%BD%AC%E6%8D%A2%E6%9C%89%E5%93%AA%E5%87%A0%E7%A7%8D"><span class="nav-text"> 9、强制类型转换有哪几种？</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#10-%E5%A6%82%E4%BD%95%E5%88%A4%E6%96%AD%E7%BB%93%E6%9E%84%E4%BD%93%E6%98%AF%E5%90%A6%E7%9B%B8%E7%AD%89%E8%83%BD%E5%90%A6%E7%94%A8-memcmp-%E5%87%BD%E6%95%B0%E5%88%A4%E6%96%AD%E7%BB%93%E6%9E%84%E4%BD%93%E7%9B%B8%E7%AD%89"><span class="nav-text"> 10、如何判断结构体是否相等？能否用 memcmp 函数判断结构体相等？</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#11-%E5%8F%82%E6%95%B0%E4%BC%A0%E9%80%92%E6%97%B6%E5%80%BC%E4%BC%A0%E9%80%92-%E5%BC%95%E7%94%A8%E4%BC%A0%E9%80%92-%E6%8C%87%E9%92%88%E4%BC%A0%E9%80%92%E7%9A%84%E5%8C%BA%E5%88%AB"><span class="nav-text"> 11、参数传递时，值传递、引用传递、指针传递的区别？</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#12-%E4%BB%80%E4%B9%88%E6%98%AF%E6%A8%A1%E6%9D%BF%E5%A6%82%E4%BD%95%E5%AE%9E%E7%8E%B0"><span class="nav-text"> 12、什么是模板？如何实现？</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#13-%E5%87%BD%E6%95%B0%E6%A8%A1%E6%9D%BF%E5%92%8C%E7%B1%BB%E6%A8%A1%E6%9D%BF%E7%9A%84%E5%8C%BA%E5%88%AB"><span class="nav-text"> 13、函数模板和类模板的区别？</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#14-%E4%BB%80%E4%B9%88%E6%98%AF%E5%8F%AF%E5%8F%98%E5%8F%82%E6%95%B0%E6%A8%A1%E6%9D%BF"><span class="nav-text"> 14、什么是可变参数模板？</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#15-%E4%BB%80%E4%B9%88%E6%98%AF%E6%A8%A1%E6%9D%BF%E7%89%B9%E5%8C%96%E4%B8%BA%E4%BB%80%E4%B9%88%E7%89%B9%E5%8C%96"><span class="nav-text"> 15、什么是模板特化？为什么特化？</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#16-include-%E5%92%8C-%E7%9A%84%E5%8C%BA%E5%88%AB"><span class="nav-text"> 16、include “” 和 &lt;&gt; 的区别</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#17-switch-%E7%9A%84-case-%E9%87%8C%E4%B8%BA%E4%BD%95%E4%B8%8D%E8%83%BD%E5%AE%9A%E4%B9%89%E5%8F%98%E9%87%8F"><span class="nav-text"> 17、switch 的 case 里为何不能定义变量</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#18-%E8%BF%AD%E4%BB%A3%E5%99%A8%E7%9A%84%E4%BD%9C%E7%94%A8"><span class="nav-text"> 18、迭代器的作用</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#19-%E6%B3%9B%E5%9E%8B%E7%BC%96%E7%A8%8B%E5%A6%82%E4%BD%95%E5%AE%9E%E7%8E%B0"><span class="nav-text"> 19、泛型编程如何实现？</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#20-%E4%BB%80%E4%B9%88%E6%98%AF%E7%B1%BB%E5%9E%8B%E8%90%83%E5%8F%96"><span class="nav-text"> 20、什么是类型萃取？</span></a></li></ol></li><li class="nav-item nav-level-1"><a class="nav-link" href="#%E4%B8%83-%E8%AE%BE%E8%AE%A1%E6%A8%A1%E5%BC%8F"><span class="nav-text"> 七、设计模式</span></a><ol class="nav-child"><li class="nav-item nav-level-2"><a class="nav-link" href="#1-%E4%BA%86%E8%A7%A3%E5%93%AA%E4%BA%9B%E8%AE%BE%E8%AE%A1%E6%A8%A1%E5%BC%8F"><span class="nav-text"> 1、了解哪些设计模式？</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#2-%E4%BB%80%E4%B9%88%E6%98%AF%E5%8D%95%E4%BE%8B%E6%A8%A1%E5%BC%8F%E5%A6%82%E4%BD%95%E5%AE%9E%E7%8E%B0%E5%BA%94%E7%94%A8%E5%9C%BA%E6%99%AF"><span class="nav-text"> 2、什么是单例模式？如何实现？应用场景？</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#3-%E4%BB%80%E4%B9%88%E6%98%AF%E5%B7%A5%E5%8E%82%E6%A8%A1%E5%BC%8F%E5%A6%82%E4%BD%95%E5%AE%9E%E7%8E%B0%E5%BA%94%E7%94%A8%E5%9C%BA%E6%99%AF"><span class="nav-text"> 3、什么是工厂模式？如何实现？应用场景？</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#4-%E4%BB%80%E4%B9%88%E6%98%AF%E8%A7%82%E5%AF%9F%E8%80%85%E6%A8%A1%E5%BC%8F%E5%A6%82%E4%BD%95%E5%AE%9E%E7%8E%B0%E5%BA%94%E7%94%A8%E5%9C%BA%E6%99%AF"><span class="nav-text"> 4、什么是观察者模式？如何实现？应用场景？</span></a></li></ol></li><li class="nav-item nav-level-1"><a class="nav-link" href="#%E5%85%AB-%E5%8F%82%E8%80%83%E8%B5%84%E6%96%99"><span class="nav-text"> 八、参考资料</span></a></li></ol></div>
      </div>
      <!--/noindex-->
     
      <div class="site-overview-wrap sidebar-panel">
        <div class="site-author motion-element" itemprop="author" itemscope itemtype="http://schema.org/Person">
    <img class="site-author-image" itemprop="image" alt="Maureen"
      src="/images/stan.jpeg">
  <p class="site-author-name" itemprop="name">Maureen</p>
  <div class="site-description" itemprop="description">心之所向，素履以往</div>
</div>
<div class="site-state-wrap motion-element">
  <nav class="site-state">
      <div class="site-state-item site-state-posts">
          <a href="/archives/">
        
          <span class="site-state-item-count">7</span>
          <span class="site-state-item-name">日志</span>
        </a>
      </div>
      <div class="site-state-item site-state-categories">
            <a href="/categories/">
          
        <span class="site-state-item-count">7</span>
        <span class="site-state-item-name">分类</span></a>
      </div>
      <div class="site-state-item site-state-tags">
            <a href="/tags/">
          
        <span class="site-state-item-count">2</span>
        <span class="site-state-item-name">标签</span></a>
      </div>
  </nav>
</div>
  <div class="links-of-author motion-element">
      <span class="links-of-author-item">
        <a href="https://github.com/maureenLiu" title="GitHub → https:&#x2F;&#x2F;github.com&#x2F;maureenLiu" rel="noopener" target="_blank"><i class="fab fa-github fa-fw"></i>GitHub</a>
      </span>
      <span class="links-of-author-item">
        <a href="https://blog.csdn.net/u011386173?spm=1000.2115.3001.5343" title="CSDN → https:&#x2F;&#x2F;blog.csdn.net&#x2F;u011386173?spm&#x3D;1000.2115.3001.5343" rel="noopener" target="_blank"><i class="crosshairs fa-fw"></i>CSDN</a>
      </span>
      <span class="links-of-author-item">
        <a href="mailto:maureen@qq.com" title="E-Mail → mailto:maureen@qq.com" rel="noopener" target="_blank"><i class="fa fa-envelope fa-fw"></i>E-Mail</a>
      </span>
  </div>
  <div class="cc-license motion-element" itemprop="license">
    <a href="https://creativecommons.org/licenses/by-nc-sa/4.0/" class="cc-opacity" rel="noopener" target="_blank"><img src="/images/cc-by-nc-sa.svg" alt="Creative Commons"></a>
  </div>



      </div>

        <div id="music163player"> 
            <iframe frameborder="no" border="0" marginwidth="0" marginheight="0" width=330 height=86 src="//music.163.com/outchain/player?type=2&id=1475596788&auto=1&height=66"></iframe> 
        </div>
        <div class="back-to-top motion-element">
          <i class="fa fa-arrow-up"></i>
          <span>0%</span>
        </div>

    </div>
  </aside>
  <div id="sidebar-dimmer"></div>


      </div>
    </main>

    <footer class="footer">
      <div class="footer-inner">
        

        

<div class="copyright">
  
  &copy; 2021 – 
  <span itemprop="copyrightYear">2022</span>
  <span class="with-love">
    <i class="fa fa-heart"></i>
  </span>
  <span class="author" itemprop="copyrightHolder">Maureen</span>
    <span class="post-meta-divider">|</span>
    <span class="post-meta-item-icon">
      <i class="fa fa-chart-area"></i>
    </span>
      <span class="post-meta-item-text">站点总字数：</span>
    <span title="站点总字数">307k</span>
    <span class="post-meta-divider">|</span>
    <span class="post-meta-item-icon">
      <i class="fa fa-coffee"></i>
    </span>
      <span class="post-meta-item-text">站点阅读时长 &asymp;</span>
    <span title="站点阅读时长">4:39</span>
</div>

        
<div class="busuanzi-count">
  <script async src="https://busuanzi.ibruce.info/busuanzi/2.3/busuanzi.pure.mini.js"></script>
    <span class="post-meta-item" id="busuanzi_container_site_uv" style="display: none;">
      <span class="post-meta-item-icon">
        <i class="fa fa-user"></i>
      </span>
      <span class="site-uv" title="总访客量">
        <span id="busuanzi_value_site_uv"></span>
      </span>
    </span>
    <span class="post-meta-divider">|</span>
    <span class="post-meta-item" id="busuanzi_container_site_pv" style="display: none;">
      <span class="post-meta-item-icon">
        <i class="fa fa-eye"></i>
      </span>
      <span class="site-pv" title="总访问量">
        <span id="busuanzi_value_site_pv"></span>
      </span>
    </span>
</div>








      </div>
    </footer>
  </div>

  
  <script src="/lib/anime.min.js"></script>
  <script src="/lib/velocity/velocity.min.js"></script>
  <script src="/lib/velocity/velocity.ui.min.js"></script>

<script src="/js/utils.js"></script>

<script src="/js/motion.js"></script>


<script src="/js/schemes/pisces.js"></script>


<script src="/js/next-boot.js"></script>




  




  
<script src="/js/local-search.js"></script>













  

  


<script>
NexT.utils.loadComments(document.querySelector('#valine-comments'), () => {
  NexT.utils.getScript('//unpkg.com/valine/dist/Valine.min.js', () => {
    var GUEST = ['nick', 'mail', 'link'];
    var guest = 'nick,mail,link';
    guest = guest.split(',').filter(item => {
      return GUEST.includes(item);
    });
    new Valine({
      el         : '#valine-comments',
      verify     : false,
      notify     : false,
      appId      : '7A7ruXkEvS4VKjoTaajLunbw-9Nh9j0Va',
      appKey     : 'E4svxhhfVsrC9eCyM8YfT8uq',
      placeholder: "Just go go",
      avatar     : 'mm',
      meta       : guest,
      pageSize   : '10' || 10,
      visitor    : false,
      lang       : 'zh-cn' || 'zh-cn',
      path       : location.pathname,
      recordIP   : false,
      serverURLs : ''
    });
  }, window.Valine);
});
</script>

<script src="/live2dw/lib/L2Dwidget.min.js?094cbace49a39548bed64abff5988b05"></script><script>L2Dwidget.init({"log":false,"pluginJsPath":"lib/","pluginModelPath":"assets/","pluginRootPath":"live2dw/","tagMode":false});</script></body>
</html>

<!-- 页面点击小红心 -->
<script type="text/javascript" src="/js/clicklove.js"></script>
